MediaRouteControllerDialog.java revision 145e93b13dd025b278665494e7be0c15b8df5986
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
19bfb90b6717bb46535d747aa50045a206965542d0Jae Seoimport static android.widget.SeekBar.OnSeekBarChangeListener;
20bfb90b6717bb46535d747aa50045a206965542d0Jae Seo
21005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.content.ContentResolver;
2211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context;
236e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kimimport android.content.res.Configuration;
246e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kimimport android.content.res.Resources;
256051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.content.res.TypedArray;
26005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap;
27005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory;
2813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.graphics.drawable.BitmapDrawable;
292ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brownimport android.graphics.drawable.Drawable;
30005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.net.Uri;
31005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.os.AsyncTask;
3211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle;
3394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException;
3494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat;
3594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat;
3694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaControllerCompat;
3794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat;
3894be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat;
39005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.support.v7.graphics.Palette;
4011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector;
4111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter;
4211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R;
4394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils;
4413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.util.DisplayMetrics;
4594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log;
4611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent;
476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.LayoutInflater;
4811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View;
496051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.ViewGroup;
506051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter;
5111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button;
5211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout;
5394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton;
5494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView;
55f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout;
566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ListView;
577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport android.widget.RelativeLayout;
58f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar;
5994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView;
6011417b1cfde8f1749905f2d735623af9214148afJeff Brown
61005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream;
62005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException;
637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport java.util.ArrayList;
646051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List;
65005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
6611417b1cfde8f1749905f2d735623af9214148afJeff Brown/**
6711417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}.
6811417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p>
6911417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route.
7011417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p>
7111417b1cfde8f1749905f2d735623af9214148afJeff Brown *
7211417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton
7311417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider
7411417b1cfde8f1749905f2d735623af9214148afJeff Brown */
7589530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog {
7611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final String TAG = "MediaRouteControllerDialog";
7711417b1cfde8f1749905f2d735623af9214148afJeff Brown
78a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo    // STOPSHIP: Remove the flag when the group volume control implementation completes.
79a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo    private static final boolean USE_GROUP = false;
80a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo
81f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // Time to wait before updating the volume when the user lets go of the seek bar
82f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // to allow the route provider time to propagate the change and publish a new
83f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // route descriptor.
84f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private static final int VOLUME_UPDATE_DELAY_MILLIS = 250;
85f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
8611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter mRouter;
8711417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouterCallback mCallback;
8811417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter.RouteInfo mRoute;
8911417b1cfde8f1749905f2d735623af9214148afJeff Brown
90eff7719415542ba819054863b0995f07742a7a8aJeff Brown    private boolean mCreated;
91e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private boolean mAttachedToWindow;
926e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    private int mOrientation;
936e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    private int mDialogWidthPortrait;
946e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    private int mDialogWidthLandscape;
9513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    private int mDialogPaddingVertical;
9611417b1cfde8f1749905f2d735623af9214148afJeff Brown
977ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private View mCustomControlView;
9811417b1cfde8f1749905f2d735623af9214148afJeff Brown
9911417b1cfde8f1749905f2d735623af9214148afJeff Brown    private Button mDisconnectButton;
10094be6100218126ce6a08bf1f56209578500b361fRoboErik    private Button mStopCastingButton;
101b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim    private ImageButton mCloseButton;
10294be6100218126ce6a08bf1f56209578500b361fRoboErik
1037ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private FrameLayout mCustomControlFrame;
10494be6100218126ce6a08bf1f56209578500b361fRoboErik    private ImageView mArtView;
1057ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private TextView mRouteNameTextView;
10694be6100218126ce6a08bf1f56209578500b361fRoboErik
107f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private boolean mVolumeControlEnabled = true;
1087ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private MediaRouteControlAdapter mControlAdapter;
1097ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private ListView mControlView;
1106051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private ListView mVolumeGroupList;
111f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
11294be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCompat mMediaController;
11394be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCallback mControllerCallback;
11494be6100218126ce6a08bf1f56209578500b361fRoboErik    private PlaybackStateCompat mState;
11594be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaDescriptionCompat mDescription;
11694be6100218126ce6a08bf1f56209578500b361fRoboErik
117005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    private FetchArtTask mFetchArtTask;
11811417b1cfde8f1749905f2d735623af9214148afJeff Brown
11911417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context) {
12011417b1cfde8f1749905f2d735623af9214148afJeff Brown        this(context, 0);
12111417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
12211417b1cfde8f1749905f2d735623af9214148afJeff Brown
12311417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context, int theme) {
12494be6100218126ce6a08bf1f56209578500b361fRoboErik        super(MediaRouterThemeHelper.createThemedContext(context), theme);
12511417b1cfde8f1749905f2d735623af9214148afJeff Brown        context = getContext();
12611417b1cfde8f1749905f2d735623af9214148afJeff Brown
12794be6100218126ce6a08bf1f56209578500b361fRoboErik        mControllerCallback = new MediaControllerCallback();
12811417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter = MediaRouter.getInstance(context);
12911417b1cfde8f1749905f2d735623af9214148afJeff Brown        mCallback = new MediaRouterCallback();
13011417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRoute = mRouter.getSelectedRoute();
131e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
13211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
13311417b1cfde8f1749905f2d735623af9214148afJeff Brown
13411417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
13511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the route that this dialog is controlling.
13611417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
13711417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouter.RouteInfo getRoute() {
13811417b1cfde8f1749905f2d735623af9214148afJeff Brown        return mRoute;
13911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
14011417b1cfde8f1749905f2d735623af9214148afJeff Brown
1416051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private MediaRouter.RouteGroup getGroup() {
1426051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        if (mRoute instanceof MediaRouter.RouteGroup) {
1436051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return (MediaRouter.RouteGroup) mRoute;
1446051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
1456051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        return null;
1466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
1476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
14811417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
14911417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Provides the subclass an opportunity to create a view that will
15011417b1cfde8f1749905f2d735623af9214148afJeff Brown     * be included within the body of the dialog to offer additional media controls
15111417b1cfde8f1749905f2d735623af9214148afJeff Brown     * for the currently playing content.
15211417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
15311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @param savedInstanceState The dialog's saved instance state.
15411417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
15511417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
15611417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View onCreateMediaControlView(Bundle savedInstanceState) {
15711417b1cfde8f1749905f2d735623af9214148afJeff Brown        return null;
15811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
15911417b1cfde8f1749905f2d735623af9214148afJeff Brown
16011417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
16111417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}.
16211417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
16311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
16411417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
16511417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View getMediaControlView() {
1667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        return mCustomControlView;
16711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
16811417b1cfde8f1749905f2d735623af9214148afJeff Brown
169eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
170f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Sets whether to enable the volume slider and volume control using the volume keys
171f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
172f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * <p>
173f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * The default value is true.
174f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * </p>
175f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
176f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public void setVolumeControlEnabled(boolean enable) {
177f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        if (mVolumeControlEnabled != enable) {
178f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            mVolumeControlEnabled = enable;
179f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            if (mCreated) {
1807ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                mControlAdapter.updateVolumeControl();
181f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            }
182f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        }
183f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
184f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
185f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
186f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Returns whether to enable the volume slider and volume control using the volume keys
187f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
188f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
189f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public boolean isVolumeControlEnabled() {
190f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        return mVolumeControlEnabled;
191f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
192f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
193f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
19494be6100218126ce6a08bf1f56209578500b361fRoboErik     * Set the session to use for metadata and transport controls. The dialog
19594be6100218126ce6a08bf1f56209578500b361fRoboErik     * will listen to changes on this session and update the UI automatically in
19694be6100218126ce6a08bf1f56209578500b361fRoboErik     * response to changes.
19794be6100218126ce6a08bf1f56209578500b361fRoboErik     *
19894be6100218126ce6a08bf1f56209578500b361fRoboErik     * @param sessionToken The token for the session to use.
199eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
200e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private void setMediaSession(MediaSessionCompat.Token sessionToken) {
20194be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
20294be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.unregisterCallback(mControllerCallback);
20394be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = null;
20494be6100218126ce6a08bf1f56209578500b361fRoboErik        }
20594be6100218126ce6a08bf1f56209578500b361fRoboErik        if (sessionToken == null) {
20694be6100218126ce6a08bf1f56209578500b361fRoboErik            return;
20794be6100218126ce6a08bf1f56209578500b361fRoboErik        }
208e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        if (!mAttachedToWindow) {
209e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            return;
210e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
21194be6100218126ce6a08bf1f56209578500b361fRoboErik        try {
21294be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = new MediaControllerCompat(getContext(), sessionToken);
21394be6100218126ce6a08bf1f56209578500b361fRoboErik        } catch (RemoteException e) {
21494be6100218126ce6a08bf1f56209578500b361fRoboErik            Log.e(TAG, "Error creating media controller in setMediaSession.", e);
21594be6100218126ce6a08bf1f56209578500b361fRoboErik        }
21694be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
21794be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.registerCallback(mControllerCallback);
218eff7719415542ba819054863b0995f07742a7a8aJeff Brown        }
21994be6100218126ce6a08bf1f56209578500b361fRoboErik        MediaMetadataCompat metadata = mMediaController == null ? null
22094be6100218126ce6a08bf1f56209578500b361fRoboErik                : mMediaController.getMetadata();
22194be6100218126ce6a08bf1f56209578500b361fRoboErik        mDescription = metadata == null ? null : metadata.getDescription();
22294be6100218126ce6a08bf1f56209578500b361fRoboErik        mState = mMediaController == null ? null : mMediaController.getPlaybackState();
22394be6100218126ce6a08bf1f56209578500b361fRoboErik        update();
224eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
225eff7719415542ba819054863b0995f07742a7a8aJeff Brown
226eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
22794be6100218126ce6a08bf1f56209578500b361fRoboErik     * Gets the description being used by the default UI.
22894be6100218126ce6a08bf1f56209578500b361fRoboErik     *
22994be6100218126ce6a08bf1f56209578500b361fRoboErik     * @return The current description.
230eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
23194be6100218126ce6a08bf1f56209578500b361fRoboErik    public MediaSessionCompat.Token getMediaSession() {
23294be6100218126ce6a08bf1f56209578500b361fRoboErik        return mMediaController == null ? null : mMediaController.getSessionToken();
233eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
234eff7719415542ba819054863b0995f07742a7a8aJeff Brown
23511417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
23611417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void onCreate(Bundle savedInstanceState) {
23711417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onCreate(savedInstanceState);
23811417b1cfde8f1749905f2d735623af9214148afJeff Brown
239a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim        setContentView(R.layout.mr_controller_material_dialog_b);
2406e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        View decorView = getWindow().getDecorView();
2416e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        int dialogHorizontalPadding = decorView.getPaddingLeft() + decorView.getPaddingRight();
2426e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        Resources res = getContext().getResources();
2436e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        mDialogWidthPortrait = res.getDimensionPixelSize(
2446e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim                R.dimen.mr_dialog_content_width_portrait) + dialogHorizontalPadding;
2456e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        mDialogWidthLandscape = res.getDimensionPixelSize(
2466e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim                R.dimen.mr_dialog_content_width_landscape) + dialogHorizontalPadding;
24713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        mDialogPaddingVertical = decorView.getPaddingTop() + decorView.getPaddingBottom();
24811417b1cfde8f1749905f2d735623af9214148afJeff Brown
24994be6100218126ce6a08bf1f56209578500b361fRoboErik        ClickListener listener = new ClickListener();
250d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown
25194be6100218126ce6a08bf1f56209578500b361fRoboErik        mDisconnectButton = (Button) findViewById(R.id.disconnect);
25294be6100218126ce6a08bf1f56209578500b361fRoboErik        mDisconnectButton.setOnClickListener(listener);
25311417b1cfde8f1749905f2d735623af9214148afJeff Brown
25494be6100218126ce6a08bf1f56209578500b361fRoboErik        mStopCastingButton = (Button) findViewById(R.id.stop);
25594be6100218126ce6a08bf1f56209578500b361fRoboErik        mStopCastingButton.setOnClickListener(listener);
25611417b1cfde8f1749905f2d735623af9214148afJeff Brown
2577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mRouteNameTextView = (TextView) findViewById(R.id.route_name);
258b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim        mCloseButton = (ImageButton) findViewById(R.id.close);
259b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim        mCloseButton.setOnClickListener(listener);
26011417b1cfde8f1749905f2d735623af9214148afJeff Brown
2617ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mCustomControlFrame = (FrameLayout) findViewById(R.id.custom_control_frame);
2627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mArtView = (ImageView) findViewById(R.id.mr_art);
2636051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
2647ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mControlAdapter = new MediaRouteControlAdapter(
2657ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                getContext(), new ArrayList<View>(), listener);
2667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mControlView = (ListView) findViewById(R.id.mr_control);
2677ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mControlView.setAdapter(mControlAdapter);
2687ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mVolumeGroupList = (ListView)findViewById(R.id.mr_volume_group_list);
26911417b1cfde8f1749905f2d735623af9214148afJeff Brown
270eff7719415542ba819054863b0995f07742a7a8aJeff Brown        mCreated = true;
2717ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mCustomControlView = onCreateMediaControlView(savedInstanceState);
2727ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        if (mCustomControlView != null) {
2737ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mCustomControlFrame.addView(mCustomControlView);
2747ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mCustomControlFrame.setVisibility(View.VISIBLE);
2757ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mArtView.setVisibility(View.GONE);
27611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
2777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        update();
27811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
27911417b1cfde8f1749905f2d735623af9214148afJeff Brown
2806e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    /**
2816e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim     * Called by {@link MediaRouteControllerDialogFragment} when the device configuration
2826e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim     * is changed.
2836e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim     */
2846e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    void onConfigurationChanged(Configuration newConfig) {
2856e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        onOrientationChanged(newConfig.orientation);
2866e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    }
2876e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim
2886e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    private void onOrientationChanged(int orientation) {
2896e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        if (!mAttachedToWindow || mOrientation == orientation) {
2906e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim            return;
2916e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        }
2926e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        mOrientation = orientation;
2936e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        getWindow().setLayout(
2946e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim                mOrientation == Configuration.ORIENTATION_LANDSCAPE
2956e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim                        ? mDialogWidthLandscape : mDialogWidthPortrait,
2966e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim                ViewGroup.LayoutParams.WRAP_CONTENT);
29713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        updateArtView();
2986e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim    }
2996e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim
30011417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
30111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onAttachedToWindow() {
30211417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onAttachedToWindow();
303e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = true;
30411417b1cfde8f1749905f2d735623af9214148afJeff Brown
30511417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback,
30611417b1cfde8f1749905f2d735623af9214148afJeff Brown                MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
307e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
3086e547065f21f1645b3e9d5b3a3fd9720be8aede8Jaewan Kim        onOrientationChanged(getContext().getResources().getConfiguration().orientation);
30911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
31011417b1cfde8f1749905f2d735623af9214148afJeff Brown
31111417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
31211417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onDetachedFromWindow() {
31311417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.removeCallback(mCallback);
314e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(null);
315e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = false;
31611417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onDetachedFromWindow();
31711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
31811417b1cfde8f1749905f2d735623af9214148afJeff Brown
31911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
32011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyDown(int keyCode, KeyEvent event) {
321ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
322ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
323ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1);
324ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
32511417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
32611417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyDown(keyCode, event);
32711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
32811417b1cfde8f1749905f2d735623af9214148afJeff Brown
32911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
33011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyUp(int keyCode, KeyEvent event) {
331ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
332ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
333ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
33411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
33511417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyUp(keyCode, event);
33611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
33711417b1cfde8f1749905f2d735623af9214148afJeff Brown
3387ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private void update() {
33911417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!mRoute.isSelected() || mRoute.isDefault()) {
34011417b1cfde8f1749905f2d735623af9214148afJeff Brown            dismiss();
3417ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
34211417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
34394be6100218126ce6a08bf1f56209578500b361fRoboErik        if (!mCreated) {
3447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
34594be6100218126ce6a08bf1f56209578500b361fRoboErik        }
3462ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown
3477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mRouteNameTextView.setText(mRoute.getName());
3487ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE);
34994be6100218126ce6a08bf1f56209578500b361fRoboErik
3507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        if (mCustomControlView == null) {
351005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            if (mFetchArtTask != null) {
352005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                mFetchArtTask.cancel(true);
35366937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang            }
354005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = new FetchArtTask();
355005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask.execute();
356f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        }
3577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mControlAdapter.updateVolumeControl();
3587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mControlAdapter.updatePlaybackControl();
359f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
360f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
361f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private boolean isVolumeControlAvailable() {
362f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        return mVolumeControlEnabled && mRoute.getVolumeHandling() ==
363f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah                MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
364f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
365f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
36613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    private void updateArtView() {
36713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        if (!(mArtView.getDrawable() instanceof BitmapDrawable)) {
368bfb90b6717bb46535d747aa50045a206965542d0Jae Seo            mArtView.setVisibility(View.GONE);
36913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            return;
37013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        }
37113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap();
37213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        if (art == null) {
373bfb90b6717bb46535d747aa50045a206965542d0Jae Seo            mArtView.setVisibility(View.GONE);
37413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            return;
37513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        }
37613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        int desiredArtHeight = getDesiredArtHeight(art.getWidth(), art.getHeight());
37713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
37813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        int dialogWidth = displayMetrics.widthPixels < displayMetrics.heightPixels
37913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                ? mDialogWidthPortrait : mDialogWidthLandscape;
38013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        View decorView = getWindow().getDecorView();
38113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        decorView.measure(dialogWidth, View.MeasureSpec.UNSPECIFIED);
38213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        // Show art if and only if it fits in the screen.
38313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        if (mArtView.getVisibility() == View.GONE) {
38413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            if (decorView.getMeasuredHeight() + desiredArtHeight <= displayMetrics.heightPixels) {
38513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                mArtView.setVisibility(View.VISIBLE);
38613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                mArtView.setMaxHeight(desiredArtHeight);
38713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            }
38813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        } else {
38913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            if (decorView.getMeasuredHeight() - mArtView.getMeasuredHeight() + desiredArtHeight
39013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    <= displayMetrics.heightPixels) {
39113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                mArtView.setMaxHeight(desiredArtHeight);
39213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            } else {
39313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                mArtView.setVisibility(View.GONE);
39413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            }
39513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        }
39613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    }
39713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim
39813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    /**
39913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     * Returns desired art height to fit into controller dialog.
40013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     */
40113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    private int getDesiredArtHeight(int originalWidth, int originalHeight) {
40213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        int dialogWidth = getWindow().getAttributes().width - mDialogPaddingVertical;
40313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        if (originalWidth >= originalHeight) {
40413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            // For landscape art, fit width to dialog width.
4055716b49c08ac172c06fdced848ec8ab599174970Jaewan Kim            return (int) ((float) dialogWidth * originalHeight / originalWidth + 0.5f);
40613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        }
40713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        // For portrait art, fit height to 16:9 ratio case's height.
4085716b49c08ac172c06fdced848ec8ab599174970Jaewan Kim        return (int) ((float) dialogWidth * 9 / 16 + 0.5f);
40913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    }
41013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim
41111417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final class MediaRouterCallback extends MediaRouter.Callback {
41211417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
41311417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
41411417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
41511417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
41611417b1cfde8f1749905f2d735623af9214148afJeff Brown
41711417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
41811417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
41911417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
42011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
42111417b1cfde8f1749905f2d735623af9214148afJeff Brown
42211417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
42311417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
42411417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (route == mRoute) {
4257ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                mControlAdapter.updateVolumeControl();
42694be6100218126ce6a08bf1f56209578500b361fRoboErik            }
42794be6100218126ce6a08bf1f56209578500b361fRoboErik        }
42894be6100218126ce6a08bf1f56209578500b361fRoboErik    }
42994be6100218126ce6a08bf1f56209578500b361fRoboErik
43094be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class MediaControllerCallback extends MediaControllerCompat.Callback {
43194be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
43294be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onSessionDestroyed() {
43394be6100218126ce6a08bf1f56209578500b361fRoboErik            if (mMediaController != null) {
43494be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController.unregisterCallback(mControllerCallback);
43594be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController = null;
43694be6100218126ce6a08bf1f56209578500b361fRoboErik            }
43794be6100218126ce6a08bf1f56209578500b361fRoboErik        }
43894be6100218126ce6a08bf1f56209578500b361fRoboErik
43994be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
44094be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onPlaybackStateChanged(PlaybackStateCompat state) {
44194be6100218126ce6a08bf1f56209578500b361fRoboErik            mState = state;
44294be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
44394be6100218126ce6a08bf1f56209578500b361fRoboErik        }
44494be6100218126ce6a08bf1f56209578500b361fRoboErik
44594be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
44694be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onMetadataChanged(MediaMetadataCompat metadata) {
44794be6100218126ce6a08bf1f56209578500b361fRoboErik            mDescription = metadata == null ? null : metadata.getDescription();
44894be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
44994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
45094be6100218126ce6a08bf1f56209578500b361fRoboErik    }
45194be6100218126ce6a08bf1f56209578500b361fRoboErik
45294be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class ClickListener implements View.OnClickListener {
45394be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
45494be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onClick(View v) {
45594be6100218126ce6a08bf1f56209578500b361fRoboErik            int id = v.getId();
45694be6100218126ce6a08bf1f56209578500b361fRoboErik            if (id == R.id.stop || id == R.id.disconnect) {
45794be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mRoute.isSelected()) {
45894be6100218126ce6a08bf1f56209578500b361fRoboErik                    mRouter.unselect(id == R.id.stop ?
45994be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_STOPPED :
46094be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_DISCONNECTED);
46194be6100218126ce6a08bf1f56209578500b361fRoboErik                }
46294be6100218126ce6a08bf1f56209578500b361fRoboErik                dismiss();
4637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            } else if (id == R.id.mr_control_play_pause) {
46494be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mMediaController != null && mState != null) {
46594be6100218126ce6a08bf1f56209578500b361fRoboErik                    if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) {
46694be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().pause();
46794be6100218126ce6a08bf1f56209578500b361fRoboErik                    } else {
46894be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().play();
46994be6100218126ce6a08bf1f56209578500b361fRoboErik                    }
47094be6100218126ce6a08bf1f56209578500b361fRoboErik                }
471b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim            } else if (id == R.id.close) {
472b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim                dismiss();
47311417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
47411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
47511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
476005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
4777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    // TODO: Consider to implement the default controls using LinearLayout instead of ListView.
4787ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private class MediaRouteControlAdapter extends ArrayAdapter<View> {
4797ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private List<View> mItemViews;
4807ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
4817ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private RelativeLayout mPlaybackControl;
4827ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private TextView mTitleView;
4837ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private TextView mSubtitleView;
4847ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private ImageButton mPlayPauseButton;
4857ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
4867ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private LinearLayout mVolumeControl;
4877ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private SeekBar mVolumeSlider;
4887ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private ImageButton mGroupExpandCollapseButton;
4897ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        private boolean mVolumeSliderTouched;
4907ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
4917ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
4927ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        public MediaRouteControlAdapter(Context context, List<View> itemViews,
4937ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                ClickListener listener) {
4947ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            super(context, 0, itemViews);
4957ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mItemViews = itemViews;
4967ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
4977ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mPlaybackControl = (RelativeLayout) LayoutInflater.from(context).inflate(
4987ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    R.layout.mr_playback_control, mControlView);
4997ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mTitleView = (TextView) mPlaybackControl.findViewById(R.id.mr_control_title);
5007ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mSubtitleView = (TextView) mPlaybackControl.findViewById(R.id.mr_control_subtitle);
5017ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mPlayPauseButton = (ImageButton) mPlaybackControl.findViewById(
5027ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    R.id.mr_control_play_pause);
5037ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mPlayPauseButton.setOnClickListener(listener);
5047ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5057ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mVolumeControl = (LinearLayout) LayoutInflater.from(context).inflate(
5067ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    R.layout.mr_volume_control, mControlView);
5077ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mVolumeSlider = (SeekBar) mVolumeControl.findViewById(R.id.mr_volume_slider);
5087ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
5097ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                private final Runnable mStopTrackingTouch = new Runnable() {
5107ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    @Override
5117ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    public void run() {
5127ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        if (mVolumeSliderTouched) {
5137ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            mVolumeSliderTouched = false;
5147ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            updateVolumeControl();
5157ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        }
5167ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    }
5177ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                };
5187ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5197ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                @Override
5207ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                public void onStartTrackingTouch(SeekBar seekBar) {
5217ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    if (mVolumeSliderTouched) {
5227ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mVolumeSlider.removeCallbacks(mStopTrackingTouch);
5237ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    } else {
5247ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mVolumeSliderTouched = true;
5257ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    }
5267ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
5277ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5287ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                @Override
5297ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                public void onStopTrackingTouch(SeekBar seekBar) {
5307ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    // Defer resetting mVolumeSliderTouched to allow the media route provider
5317ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    // a little time to settle into its new state and publish the final
5327ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    // volume update.
5337ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
5347ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
5357ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5367ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                @Override
5377ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
5387ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    if (fromUser) {
5397ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mRoute.requestSetVolume(progress);
5407ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    }
5417ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
5427ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            });
5437ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            TypedArray styledAttributes = context.obtainStyledAttributes(new int[] {
5457ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    R.attr.mediaRouteExpandGroupDrawable,
5467ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    R.attr.mediaRouteCollapseGroupDrawable
5477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            });
5487ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            final Drawable expandGroupDrawable = styledAttributes.getDrawable(0);
5497ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1);
5507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            styledAttributes.recycle();
5517ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5527ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mGroupExpandCollapseButton = (ImageButton) mVolumeControl.findViewById(
5537ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    R.id.mr_group_expand_collapse);
5547ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() {
5557ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                private boolean mIsExpanded;
5567ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                @Override
5587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                public void onClick(View v) {
5597ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mIsExpanded = !mIsExpanded;
5607ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    if (mIsExpanded) {
5617ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable);
5627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mVolumeGroupList.setVisibility(View.VISIBLE);
5637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mVolumeGroupList.setAdapter(
5647ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                                new VolumeGroupAdapter(getContext(), getGroup().getRoutes()));
5657ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    } else {
5667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable);
5677ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mVolumeGroupList.setVisibility(View.GONE);
5687ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    }
5697ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
5707ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            });
5717ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        }
5727ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5737ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        @Override
5747ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        public View getView(final int position, View convertView, ViewGroup parent) {
5757ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return mItemViews.get(position);
5767ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        }
5777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5787ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        public void updateVolumeControl() {
5797ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            if (!mVolumeSliderTouched) {
5807ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                if (isVolumeControlAvailable()) {
5817ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    if (!mItemViews.contains(mVolumeControl)) {
5827ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mItemViews.add(mVolumeControl);
5837ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
5847ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        notifyDataSetChanged();
5857ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    }
5867ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mVolumeSlider.setMax(mRoute.getVolumeMax());
5877ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mVolumeSlider.setProgress(mRoute.getVolume());
5887ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    if (USE_GROUP) {
5897ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        if (getGroup() == null) {
5907ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            mGroupExpandCollapseButton.setVisibility(View.GONE);
5917ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        } else {
5927ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            mGroupExpandCollapseButton.setVisibility(View.VISIBLE);
5937ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            VolumeGroupAdapter adapter =
5947ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                                    (VolumeGroupAdapter) mVolumeGroupList.getAdapter();
5957ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            if (adapter != null) {
5967ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                                adapter.notifyDataSetChanged();
5977ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            }
5987ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        }
5997ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    }
6007ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                } else if (mItemViews.contains(mVolumeControl)) {
6017ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mItemViews.remove(mVolumeControl);
6027ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    notifyDataSetChanged();
6037ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
6044bae6b7e7005d631aed69b13cf0abb5dbff64802Dongwon Kang                mControlView.setVisibility(mItemViews.isEmpty() ? View.GONE : View.VISIBLE);
6057ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            }
6067ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        }
6077ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
6087ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        public void updatePlaybackControl() {
6094bae6b7e7005d631aed69b13cf0abb5dbff64802Dongwon Kang            if (mCustomControlView == null && (mDescription != null || mState != null)) {
6107ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                if (!mItemViews.contains(mPlaybackControl)) {
6117ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mItemViews.add(0, mPlaybackControl);
6127ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    notifyDataSetChanged();
6137ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
6147ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                CharSequence title = mDescription == null ? null : mDescription.getTitle();
6157ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                boolean hasTitle = !TextUtils.isEmpty(title);
6167ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
6177ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle();
6187ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                boolean hasSubtitle = !TextUtils.isEmpty(subtitle);
6197ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
6207ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                if (!hasTitle && !hasSubtitle) {
62177367b4a1871417198d0399d9ad074314c758567Jae Seo                    if (mRoute.getPresentationDisplayId()
62277367b4a1871417198d0399d9ad074314c758567Jae Seo                            != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) {
62377367b4a1871417198d0399d9ad074314c758567Jae Seo                        // The user is currently casting screen.
62477367b4a1871417198d0399d9ad074314c758567Jae Seo                        mTitleView.setText(R.string.mr_controller_casting_screen);
62577367b4a1871417198d0399d9ad074314c758567Jae Seo                    } else {
62677367b4a1871417198d0399d9ad074314c758567Jae Seo                        mTitleView.setText(R.string.mr_controller_no_info_available);
62777367b4a1871417198d0399d9ad074314c758567Jae Seo                    }
6287ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mTitleView.setEnabled(false);
6297ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mTitleView.setVisibility(View.VISIBLE);
6307ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mSubtitleView.setVisibility(View.GONE);
6317ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                } else {
6327ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mTitleView.setText(title);
6337ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mTitleView.setEnabled(hasTitle);
6347ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mTitleView.setVisibility(hasTitle ? View.VISIBLE : View.GONE);
6357ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mSubtitleView.setText(subtitle);
6367ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    mSubtitleView.setVisibility(hasSubtitle ? View.VISIBLE : View.GONE);
6377ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
6387ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                if (mState != null) {
6397ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
6407ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
6417ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
6427ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
6437ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
6447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                            | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
6457ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    if (isPlaying && supportsPause) {
6467ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mPlayPauseButton.setVisibility(View.VISIBLE);
6477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
6487ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                                getContext(), R.attr.mediaRoutePauseDrawable));
6497ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mPlayPauseButton.setContentDescription(getContext().getResources()
6507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                                .getText(R.string.mr_controller_pause));
6517ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    } else if (!isPlaying && supportsPlay) {
6527ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mPlayPauseButton.setVisibility(View.VISIBLE);
6537ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
6547ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                                getContext(), R.attr.mediaRoutePlayDrawable));
6557ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mPlayPauseButton.setContentDescription(getContext().getResources()
6567ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                                .getText(R.string.mr_controller_play));
6577ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    } else {
6587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        mPlayPauseButton.setVisibility(View.GONE);
6597ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                    }
6607ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                }
6617ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            } else if (mItemViews.contains(mPlaybackControl)) {
6627ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                mItemViews.remove(mPlaybackControl);
6637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                notifyDataSetChanged();
6647ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            }
6654bae6b7e7005d631aed69b13cf0abb5dbff64802Dongwon Kang            mControlView.setVisibility(mItemViews.isEmpty() ? View.GONE : View.VISIBLE);
6667ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        }
6677ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    }
6687ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim
6696051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> {
6700e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo        final static float DISABLED_ALPHA = .3f;
6710e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
6726051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        final OnSeekBarChangeListener mOnSeekBarChangeListener = new OnSeekBarChangeListener() {
6736051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            @Override
6746051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
6756051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                if (fromUser) {
6766051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                    int position = (int) seekBar.getTag();
6776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                    getGroup().getRouteAt(position).requestSetVolume(progress);
6786051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                }
6796051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
6806051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
6816051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            @Override
6826051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            public void onStartTrackingTouch(SeekBar seekBar) {
6836051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                // TODO: Implement
6846051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
6856051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
6866051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            @Override
6876051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            public void onStopTrackingTouch(SeekBar seekBar) {
6886051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                // TODO: Implement
6896051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
6906051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        };
6916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
6926051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) {
6936051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            super(context, 0, objects);
6946051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
6956051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
6966051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        @Override
6976051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public View getView(final int position, View convertView, ViewGroup parent) {
6986051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            View v = convertView;
6996051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (v == null) {
7006051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                v = LayoutInflater.from(getContext()).inflate(
701a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim                        R.layout.mr_controller_volume_item, null);
7026051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
7036051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            MediaRouter.RouteInfo route = getItem(position);
7046051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (route != null) {
7050e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                boolean isEnabled = route.isEnabled();
7060e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
7077ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                TextView routeName = (TextView) v.findViewById(R.id.mr_name);
7080e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setEnabled(isEnabled);
7090e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setText(route.getName());
7106051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
7117ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                SeekBar volumeSlider = (SeekBar) v.findViewById(R.id.mr_volume_slider);
7120e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                volumeSlider.setEnabled(isEnabled);
7136051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                volumeSlider.setTag(position);
7140e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                if (isEnabled) {
7150e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    if (route.getVolumeHandling()
7160e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                            == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) {
7170e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(route.getVolumeMax());
7180e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(route.getVolume());
7190e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setOnSeekBarChangeListener(mOnSeekBarChangeListener);
7200e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    } else {
7210e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(100);
7220e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(100);
7230e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setEnabled(false);
7240e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    }
7250e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                }
7260e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                // TODO: Find a way to hide the scroll thumb.
7270e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                // if (Build.VERSION.SDK_INT >= 16) {
7280e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                //     volumeSlider.getThumb().setAlpha(isEnabled ? 255 : 0);
7290e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                // }
7300e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
7310e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                ImageView volumeItemIcon =
7327ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        (ImageView) v.findViewById(R.id.mr_volume_item_icon);
73377367b4a1871417198d0399d9ad074314c758567Jae Seo                volumeItemIcon.setAlpha(isEnabled ? 255 : (int) (255 * DISABLED_ALPHA));
7346051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
7356051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return v;
7366051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
7376051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
7386051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
739005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> {
740005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        private int mBackgroundColor;
741005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
742005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
743005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        protected Bitmap doInBackground(Void... arg) {
74413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            Bitmap art = null;
745005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            if (mDescription == null) {
746005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                return null;
747005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
748005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            if (mDescription.getIconBitmap() != null) {
74913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                art = mDescription.getIconBitmap();
750005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            } else if (mDescription.getIconUri() != null) {
751005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                Uri iconUri = mDescription.getIconUri();
752005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                String scheme = iconUri.getScheme();
753005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                if (!(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
754005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        || ContentResolver.SCHEME_CONTENT.equals(scheme)
755005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        || ContentResolver.SCHEME_FILE.equals(scheme))) {
756005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    Log.w(TAG, "Icon Uri should point to local resources.");
757005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    return null;
758005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                }
759005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                BufferedInputStream stream = null;
760005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                try {
761005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    stream = new BufferedInputStream(
762005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                            getContext().getContentResolver().openInputStream(iconUri));
763005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
76413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Query art size.
765005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.Options options = new BitmapFactory.Options();
766005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = true;
767005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.decodeStream(stream, null, options);
76813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    if (options.outWidth == 0 || options.outHeight == 0) {
76913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                        return null;
77013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    }
77113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Rewind the stream in order to restart art decoding.
772005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    try {
773005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.reset();
774005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    } catch (IOException e) {
775005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        // Failed to rewind the stream, try to reopen it.
776005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.close();
777005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream = new BufferedInputStream(getContext().getContentResolver()
778005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                                .openInputStream(iconUri));
779005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
78013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Calculate required size to decode the art and possibly resize it.
781005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = false;
78213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight);
78313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int ratio = options.outHeight / reqHeight;
784005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio));
785005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (isCancelled()) {
786005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        return null;
787005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
78813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    art = BitmapFactory.decodeStream(stream, null, options);
789005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } catch (IOException e){
790005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    Log.w(TAG, "Unable to open content: " + iconUri, e);
791005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } finally {
792005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (stream != null) {
793005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        try {
794005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                            stream.close();
795005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        } catch (IOException e) {
796005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        }
797005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
798005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                }
799005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
800145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim            if (art != null && art.getWidth() < art.getHeight()) {
801145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                // Portrait art requires background color.
802145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                Palette palette = new Palette.Builder(art).maximumColorCount(1).generate();
803145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                mBackgroundColor = (palette.getSwatches() == null)
804145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                        ? 0 : palette.getSwatches().get(0).getRgb();
805005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
80613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            return art;
807005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
808005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
809005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
810005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        protected void onCancelled() {
811005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = null;
812005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
813005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
814005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
81513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        protected void onPostExecute(Bitmap art) {
816005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = null;
81713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            mArtView.setImageBitmap(art);
81813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            mArtView.setBackgroundColor(mBackgroundColor);
81913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            updateArtView();
820005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
821005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    }
8226051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo}
823