MediaRouteControllerDialog.java revision 7447b1958129579090ee279caac7d703dba2ad28
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;
23c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kimimport android.content.res.Resources;
246051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.content.res.TypedArray;
25005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap;
26005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory;
272c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kimimport android.graphics.Rect;
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;
4494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log;
4506991009e52024cbb3dde550988e06149e77a269Jae Seoimport android.util.TypedValue;
4611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent;
476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.LayoutInflater;
4811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View;
4940dd800ece983a94ea6a26a27481da50f489e7c8Jaewan Kimimport android.view.View.MeasureSpec;
506051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.ViewGroup;
5186dcb627078ea297c4337ed634fc3fe874e23897Jae Seoimport android.view.ViewTreeObserver;
526051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter;
5311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button;
5411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout;
5594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton;
5694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView;
57f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout;
586051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ListView;
597ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport android.widget.RelativeLayout;
60f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar;
6194be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView;
6211417b1cfde8f1749905f2d735623af9214148afJeff Brown
63005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream;
64005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException;
656051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List;
66005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
6711417b1cfde8f1749905f2d735623af9214148afJeff Brown/**
6811417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}.
6911417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p>
7011417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route.
7111417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p>
7211417b1cfde8f1749905f2d735623af9214148afJeff Brown *
7311417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton
7411417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider
7511417b1cfde8f1749905f2d735623af9214148afJeff Brown */
7689530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog {
7711417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final String TAG = "MediaRouteControllerDialog";
7811417b1cfde8f1749905f2d735623af9214148afJeff Brown
79a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo    // STOPSHIP: Remove the flag when the group volume control implementation completes.
80a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo    private static final boolean USE_GROUP = false;
81a4bcfe765789ebef71c36cbb2dba3f9f881fa5b4Jae Seo
82f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // Time to wait before updating the volume when the user lets go of the seek bar
83f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // to allow the route provider time to propagate the change and publish a new
84f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // route descriptor.
85f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private static final int VOLUME_UPDATE_DELAY_MILLIS = 250;
86435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private static final int VOLUME_SLIDER_TAG_MASTER = 0;
87435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private static final int VOLUME_SLIDER_TAG_BASE = 100;
88f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
8906991009e52024cbb3dde550988e06149e77a269Jae Seo    private static final int BUTTON_NEUTRAL_RES_ID = android.R.id.button3;
9006991009e52024cbb3dde550988e06149e77a269Jae Seo    private static final int BUTTON_DISCONNECT_RES_ID = android.R.id.button2;
9106991009e52024cbb3dde550988e06149e77a269Jae Seo    private static final int BUTTON_STOP_RES_ID = android.R.id.button1;
9206991009e52024cbb3dde550988e06149e77a269Jae Seo
9311417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter mRouter;
9411417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouterCallback mCallback;
9511417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter.RouteInfo mRoute;
9611417b1cfde8f1749905f2d735623af9214148afJeff Brown
97eff7719415542ba819054863b0995f07742a7a8aJeff Brown    private boolean mCreated;
98e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private boolean mAttachedToWindow;
99e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo
100f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo    private int mDialogContentWidth;
10111417b1cfde8f1749905f2d735623af9214148afJeff Brown
1027ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private View mCustomControlView;
10311417b1cfde8f1749905f2d735623af9214148afJeff Brown
10411417b1cfde8f1749905f2d735623af9214148afJeff Brown    private Button mDisconnectButton;
10594be6100218126ce6a08bf1f56209578500b361fRoboErik    private Button mStopCastingButton;
1061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private ImageButton mPlayPauseButton;
107b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim    private ImageButton mCloseButton;
1081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private ImageButton mGroupExpandCollapseButton;
10994be6100218126ce6a08bf1f56209578500b361fRoboErik
1101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private FrameLayout mCustomControlLayout;
1112b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang    private FrameLayout mDefaultControlLayout;
11294be6100218126ce6a08bf1f56209578500b361fRoboErik    private ImageView mArtView;
1131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private TextView mTitleView;
1141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private TextView mSubtitleView;
1157ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private TextView mRouteNameTextView;
11694be6100218126ce6a08bf1f56209578500b361fRoboErik
117f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private boolean mVolumeControlEnabled = true;
1182c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    // Layout for media controllers including play/pause button, volume slider,
1192c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    // and group volume sliders.
1208e1281a26eaabd6422fd84c11010134a0a9c3338Jaewan Kim    private LinearLayout mMediaControlLayout;
1212c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    // Layout for media controllers including play/pause button and volume slider.
1222c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    private LinearLayout mMediaMainControlLayout;
1231ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private RelativeLayout mPlaybackControl;
1241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private LinearLayout mVolumeControl;
1251ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private View mDividerView;
1261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
1276051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private ListView mVolumeGroupList;
1281ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private SeekBar mVolumeSlider;
129435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private VolumeChangeListener mVolumeChangeListener;
1301ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private boolean mVolumeSliderTouched;
131c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListItemIconSize;
132c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListItemHeight;
133c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListMaxHeight;
134c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private final int mVolumeGroupListPaddingTop;
135f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
13694be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCompat mMediaController;
13794be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCallback mControllerCallback;
13894be6100218126ce6a08bf1f56209578500b361fRoboErik    private PlaybackStateCompat mState;
13994be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaDescriptionCompat mDescription;
14094be6100218126ce6a08bf1f56209578500b361fRoboErik
141005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    private FetchArtTask mFetchArtTask;
1428bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo    private Bitmap mArtIconBitmap;
1438bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo    private Uri mArtIconUri;
1442b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang    private boolean mIsGroupExpanded;
14511417b1cfde8f1749905f2d735623af9214148afJeff Brown
14611417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context) {
14711417b1cfde8f1749905f2d735623af9214148afJeff Brown        this(context, 0);
14811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
14911417b1cfde8f1749905f2d735623af9214148afJeff Brown
15011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context, int theme) {
15194be6100218126ce6a08bf1f56209578500b361fRoboErik        super(MediaRouterThemeHelper.createThemedContext(context), theme);
15211417b1cfde8f1749905f2d735623af9214148afJeff Brown        context = getContext();
15311417b1cfde8f1749905f2d735623af9214148afJeff Brown
15494be6100218126ce6a08bf1f56209578500b361fRoboErik        mControllerCallback = new MediaControllerCallback();
15511417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter = MediaRouter.getInstance(context);
15611417b1cfde8f1749905f2d735623af9214148afJeff Brown        mCallback = new MediaRouterCallback();
15711417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRoute = mRouter.getSelectedRoute();
158e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
159c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListPaddingTop = context.getResources().getDimensionPixelSize(
160c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_padding_top);
16111417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
16211417b1cfde8f1749905f2d735623af9214148afJeff Brown
16311417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
16411417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the route that this dialog is controlling.
16511417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
16611417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouter.RouteInfo getRoute() {
16711417b1cfde8f1749905f2d735623af9214148afJeff Brown        return mRoute;
16811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
16911417b1cfde8f1749905f2d735623af9214148afJeff Brown
1706051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private MediaRouter.RouteGroup getGroup() {
1716051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        if (mRoute instanceof MediaRouter.RouteGroup) {
1726051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return (MediaRouter.RouteGroup) mRoute;
1736051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
1746051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        return null;
1756051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
1766051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
17711417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
17811417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Provides the subclass an opportunity to create a view that will
17911417b1cfde8f1749905f2d735623af9214148afJeff Brown     * be included within the body of the dialog to offer additional media controls
18011417b1cfde8f1749905f2d735623af9214148afJeff Brown     * for the currently playing content.
18111417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
18211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @param savedInstanceState The dialog's saved instance state.
18311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
18411417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
18511417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View onCreateMediaControlView(Bundle savedInstanceState) {
18611417b1cfde8f1749905f2d735623af9214148afJeff Brown        return null;
18711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
18811417b1cfde8f1749905f2d735623af9214148afJeff Brown
18911417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
19011417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}.
19111417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
19211417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
19311417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
19411417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View getMediaControlView() {
1957ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        return mCustomControlView;
19611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
19711417b1cfde8f1749905f2d735623af9214148afJeff Brown
198eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
199f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Sets whether to enable the volume slider and volume control using the volume keys
200f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
201f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * <p>
202f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * The default value is true.
203f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * </p>
204f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
205f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public void setVolumeControlEnabled(boolean enable) {
206f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        if (mVolumeControlEnabled != enable) {
207f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            mVolumeControlEnabled = enable;
208f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            if (mCreated) {
2091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                updateVolumeControl();
210f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            }
211f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        }
212f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
213f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
214f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
215f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Returns whether to enable the volume slider and volume control using the volume keys
216f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
217f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
218f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public boolean isVolumeControlEnabled() {
219f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        return mVolumeControlEnabled;
220f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
221f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
222f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
22394be6100218126ce6a08bf1f56209578500b361fRoboErik     * Set the session to use for metadata and transport controls. The dialog
22494be6100218126ce6a08bf1f56209578500b361fRoboErik     * will listen to changes on this session and update the UI automatically in
22594be6100218126ce6a08bf1f56209578500b361fRoboErik     * response to changes.
22694be6100218126ce6a08bf1f56209578500b361fRoboErik     *
22794be6100218126ce6a08bf1f56209578500b361fRoboErik     * @param sessionToken The token for the session to use.
228eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
229e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private void setMediaSession(MediaSessionCompat.Token sessionToken) {
23094be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
23194be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.unregisterCallback(mControllerCallback);
23294be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = null;
23394be6100218126ce6a08bf1f56209578500b361fRoboErik        }
23494be6100218126ce6a08bf1f56209578500b361fRoboErik        if (sessionToken == null) {
23594be6100218126ce6a08bf1f56209578500b361fRoboErik            return;
23694be6100218126ce6a08bf1f56209578500b361fRoboErik        }
237e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        if (!mAttachedToWindow) {
238e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            return;
239e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
24094be6100218126ce6a08bf1f56209578500b361fRoboErik        try {
24194be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = new MediaControllerCompat(getContext(), sessionToken);
24294be6100218126ce6a08bf1f56209578500b361fRoboErik        } catch (RemoteException e) {
24394be6100218126ce6a08bf1f56209578500b361fRoboErik            Log.e(TAG, "Error creating media controller in setMediaSession.", e);
24494be6100218126ce6a08bf1f56209578500b361fRoboErik        }
24594be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
24694be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.registerCallback(mControllerCallback);
247eff7719415542ba819054863b0995f07742a7a8aJeff Brown        }
24894be6100218126ce6a08bf1f56209578500b361fRoboErik        MediaMetadataCompat metadata = mMediaController == null ? null
24994be6100218126ce6a08bf1f56209578500b361fRoboErik                : mMediaController.getMetadata();
25094be6100218126ce6a08bf1f56209578500b361fRoboErik        mDescription = metadata == null ? null : metadata.getDescription();
25194be6100218126ce6a08bf1f56209578500b361fRoboErik        mState = mMediaController == null ? null : mMediaController.getPlaybackState();
25294be6100218126ce6a08bf1f56209578500b361fRoboErik        update();
253eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
254eff7719415542ba819054863b0995f07742a7a8aJeff Brown
255eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
25694be6100218126ce6a08bf1f56209578500b361fRoboErik     * Gets the description being used by the default UI.
25794be6100218126ce6a08bf1f56209578500b361fRoboErik     *
25894be6100218126ce6a08bf1f56209578500b361fRoboErik     * @return The current description.
259eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
26094be6100218126ce6a08bf1f56209578500b361fRoboErik    public MediaSessionCompat.Token getMediaSession() {
26194be6100218126ce6a08bf1f56209578500b361fRoboErik        return mMediaController == null ? null : mMediaController.getSessionToken();
262eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
263eff7719415542ba819054863b0995f07742a7a8aJeff Brown
26411417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
26511417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void onCreate(Bundle savedInstanceState) {
26611417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onCreate(savedInstanceState);
26711417b1cfde8f1749905f2d735623af9214148afJeff Brown
268a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim        setContentView(R.layout.mr_controller_material_dialog_b);
269f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo
27006991009e52024cbb3dde550988e06149e77a269Jae Seo        // Remove the neutral button.
27106991009e52024cbb3dde550988e06149e77a269Jae Seo        findViewById(BUTTON_NEUTRAL_RES_ID).setVisibility(View.GONE);
27206991009e52024cbb3dde550988e06149e77a269Jae Seo
27394be6100218126ce6a08bf1f56209578500b361fRoboErik        ClickListener listener = new ClickListener();
274d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown
27506991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton = (Button) findViewById(BUTTON_DISCONNECT_RES_ID);
27606991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton.setText(R.string.mr_controller_disconnect);
27794be6100218126ce6a08bf1f56209578500b361fRoboErik        mDisconnectButton.setOnClickListener(listener);
27811417b1cfde8f1749905f2d735623af9214148afJeff Brown
27906991009e52024cbb3dde550988e06149e77a269Jae Seo        mStopCastingButton = (Button) findViewById(BUTTON_STOP_RES_ID);
28006991009e52024cbb3dde550988e06149e77a269Jae Seo        mStopCastingButton.setText(R.string.mr_controller_stop);
28194be6100218126ce6a08bf1f56209578500b361fRoboErik        mStopCastingButton.setOnClickListener(listener);
28211417b1cfde8f1749905f2d735623af9214148afJeff Brown
28306991009e52024cbb3dde550988e06149e77a269Jae Seo        TypedValue value = new TypedValue();
28406991009e52024cbb3dde550988e06149e77a269Jae Seo        if (getContext().getTheme().resolveAttribute(R.attr.colorPrimary, value, true)) {
28506991009e52024cbb3dde550988e06149e77a269Jae Seo            mDisconnectButton.setTextColor(value.data);
28606991009e52024cbb3dde550988e06149e77a269Jae Seo            mStopCastingButton.setTextColor(value.data);
28706991009e52024cbb3dde550988e06149e77a269Jae Seo        }
28806991009e52024cbb3dde550988e06149e77a269Jae Seo
2891ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mRouteNameTextView = (TextView) findViewById(R.id.mr_name);
2901ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mCloseButton = (ImageButton) findViewById(R.id.mr_close);
291b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim        mCloseButton.setOnClickListener(listener);
2921ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mCustomControlLayout = (FrameLayout) findViewById(R.id.mr_custom_control);
2932b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang        mDefaultControlLayout = (FrameLayout) findViewById(R.id.mr_default_control);
2947ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mArtView = (ImageView) findViewById(R.id.mr_art);
2956051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
2968e1281a26eaabd6422fd84c11010134a0a9c3338Jaewan Kim        mMediaControlLayout = (LinearLayout) findViewById(R.id.mr_media_control);
2972c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        mMediaMainControlLayout = (LinearLayout) findViewById(R.id.mr_media_main_control);
2981ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mDividerView = findViewById(R.id.mr_control_divider);
2991ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
3001ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mPlaybackControl = (RelativeLayout) findViewById(R.id.mr_playback_control);
3011ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mTitleView = (TextView) findViewById(R.id.mr_control_title);
3021ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mSubtitleView = (TextView) findViewById(R.id.mr_control_subtitle);
3031ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mPlayPauseButton = (ImageButton) findViewById(R.id.mr_control_play_pause);
3041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mPlayPauseButton.setOnClickListener(listener);
3051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
3061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mVolumeControl = (LinearLayout) findViewById(R.id.mr_volume_control);
3071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mVolumeSlider = (SeekBar) findViewById(R.id.mr_volume_slider);
308435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeSlider.setTag(VOLUME_SLIDER_TAG_MASTER);
309435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeChangeListener = new VolumeChangeListener();
310435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
3111ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
3121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        TypedArray styledAttributes = getContext().obtainStyledAttributes(new int[] {
3131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                R.attr.mediaRouteExpandGroupDrawable,
3141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                R.attr.mediaRouteCollapseGroupDrawable
3151ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        });
3161ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        final Drawable expandGroupDrawable = styledAttributes.getDrawable(0);
3171ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1);
3181ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        styledAttributes.recycle();
3191ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
320c2b193ac8bed52e8059178a80cb972e8229e528cJae Seo        final String expandGroupDescription = getContext().getString(
321c2b193ac8bed52e8059178a80cb972e8229e528cJae Seo                R.string.mr_controller_expand_group);
322c2b193ac8bed52e8059178a80cb972e8229e528cJae Seo        final String collapseGroupDescription = getContext().getString(
323c2b193ac8bed52e8059178a80cb972e8229e528cJae Seo                R.string.mr_controller_collapse_group);
324c2b193ac8bed52e8059178a80cb972e8229e528cJae Seo
3257ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mVolumeGroupList = (ListView)findViewById(R.id.mr_volume_group_list);
3261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mGroupExpandCollapseButton = (ImageButton) findViewById(R.id.mr_group_expand_collapse);
3271ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() {
3281ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            @Override
3291ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            public void onClick(View v) {
3302b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang                mIsGroupExpanded = !mIsGroupExpanded;
3312b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang                if (mIsGroupExpanded) {
3321ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable);
333c2b193ac8bed52e8059178a80cb972e8229e528cJae Seo                    mGroupExpandCollapseButton.setContentDescription(collapseGroupDescription);
3341ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mVolumeGroupList.setVisibility(View.VISIBLE);
3351ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mVolumeGroupList.setAdapter(
3361ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            new VolumeGroupAdapter(getContext(), getGroup().getRoutes()));
3371ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                } else {
3381ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable);
339c2b193ac8bed52e8059178a80cb972e8229e528cJae Seo                    mGroupExpandCollapseButton.setContentDescription(expandGroupDescription);
3401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mVolumeGroupList.setVisibility(View.GONE);
3411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
3422c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                updateLayoutHeight();
3431ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
3441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        });
34511417b1cfde8f1749905f2d735623af9214148afJeff Brown
3467ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mCustomControlView = onCreateMediaControlView(savedInstanceState);
3477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        if (mCustomControlView != null) {
3481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            mCustomControlLayout.addView(mCustomControlView);
3491ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            mCustomControlLayout.setVisibility(View.VISIBLE);
3507ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            mArtView.setVisibility(View.GONE);
35111417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
35286a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo        mCreated = true;
353d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        updateLayout();
354d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    }
355d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
356d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    /**
357d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo     * Sets the width of the dialog. Also called when configuration changes.
358d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo     */
359d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    void updateLayout() {
360d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        int width = MediaRouteDialogHelper.getDialogWidth(getContext());
361d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        getWindow().setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT);
362d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
363d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        View decorView = getWindow().getDecorView();
364d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        mDialogContentWidth = width - decorView.getPaddingLeft() - decorView.getPaddingRight();
365d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
366c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        Resources res = getContext().getResources();
367c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListItemIconSize = res.getDimensionPixelSize(
368c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_item_icon_size);
369c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListItemHeight = res.getDimensionPixelSize(
370c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_item_height);
371c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListMaxHeight = res.getDimensionPixelSize(
372c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_max_height);
373c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim
374c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        // Ensure the mArtView is updated.
375c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        mArtIconBitmap = null;
376c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        mArtIconUri = null;
3777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        update();
37811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
37911417b1cfde8f1749905f2d735623af9214148afJeff Brown
38011417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
38111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onAttachedToWindow() {
38211417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onAttachedToWindow();
383e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = true;
38411417b1cfde8f1749905f2d735623af9214148afJeff Brown
38511417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback,
38611417b1cfde8f1749905f2d735623af9214148afJeff Brown                MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
387e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
38811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
38911417b1cfde8f1749905f2d735623af9214148afJeff Brown
39011417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
39111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onDetachedFromWindow() {
39211417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.removeCallback(mCallback);
393e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(null);
394e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = false;
39511417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onDetachedFromWindow();
39611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
39711417b1cfde8f1749905f2d735623af9214148afJeff Brown
39811417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
39911417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyDown(int keyCode, KeyEvent event) {
400ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
401ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
402ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1);
403ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
40411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
40511417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyDown(keyCode, event);
40611417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
40711417b1cfde8f1749905f2d735623af9214148afJeff Brown
40811417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
40911417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyUp(int keyCode, KeyEvent event) {
410ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
411ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
412ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
41311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
41411417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyUp(keyCode, event);
41511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
41611417b1cfde8f1749905f2d735623af9214148afJeff Brown
4177ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private void update() {
41811417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!mRoute.isSelected() || mRoute.isDefault()) {
41911417b1cfde8f1749905f2d735623af9214148afJeff Brown            dismiss();
4207ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
42111417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
42294be6100218126ce6a08bf1f56209578500b361fRoboErik        if (!mCreated) {
4237ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
42494be6100218126ce6a08bf1f56209578500b361fRoboErik        }
4252ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown
4267ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mRouteNameTextView.setText(mRoute.getName());
42706991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE);
42894be6100218126ce6a08bf1f56209578500b361fRoboErik
4297ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        if (mCustomControlView == null) {
430005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            if (mFetchArtTask != null) {
431005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                mFetchArtTask.cancel(true);
43266937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang            }
433005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = new FetchArtTask();
434005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask.execute();
435f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        }
4361ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        updateVolumeControl();
4371ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        updatePlaybackControl();
4381ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    }
4391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
4402c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    private boolean isPlaybackControlAvailable() {
4412c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        return mCustomControlView == null && (mDescription != null || mState != null);
4422c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    }
4432c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
4443fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim    /**
4453fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * Returns the height of main media controller which includes playback control and master
4463fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * volume control.
4473fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     */
4482c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    private int getMainControllerHeight(boolean showPlaybackControl) {
4492c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int height = 0;
4502c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        if (showPlaybackControl || mVolumeControl.getVisibility() == View.VISIBLE) {
4512c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            height += mMediaMainControlLayout.getPaddingTop()
4522c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                    + mMediaMainControlLayout.getPaddingBottom();
4532c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (showPlaybackControl) {
4542c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                height +=  mPlaybackControl.getMeasuredHeight();
4552c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
4562c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (mVolumeControl.getVisibility() == View.VISIBLE) {
4572c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                height += mVolumeControl.getMeasuredHeight();
4582c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
4592c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (showPlaybackControl && mVolumeControl.getVisibility() == View.VISIBLE) {
4602c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                height += mDividerView.getMeasuredHeight();
4612c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
4622c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
4632c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        return height;
4642c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    }
4652c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
466aaa885dc21bf5f526e1d3897e26ade96e1fae9ccJaewan Kim    private void updateMediaControlVisibility(boolean showPlaybackControl) {
46792fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        // TODO: Update the top and bottom padding of the control layout according to the display
46892fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        // height.
46992fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        mDividerView.setVisibility((mVolumeControl.getVisibility() == View.VISIBLE
470aaa885dc21bf5f526e1d3897e26ade96e1fae9ccJaewan Kim                && showPlaybackControl) ? View.VISIBLE : View.GONE);
47192fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        mMediaControlLayout.setVisibility((mVolumeControl.getVisibility() == View.GONE
472f8e1601db320e5bde6cb5ddcd4ecea187e3d4362Sungsoo Lim                && !showPlaybackControl) ? View.GONE : View.VISIBLE);
47386dcb627078ea297c4337ed634fc3fe874e23897Jae Seo    }
47486dcb627078ea297c4337ed634fc3fe874e23897Jae Seo
47586dcb627078ea297c4337ed634fc3fe874e23897Jae Seo    private void updateLayoutHeight() {
47686dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // We need to defer the update until the first layout has occurred, as we don't yet know the
47786dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // overall visible display size in which the window this view is attached to has been
47886dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // positioned in.
47986dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        ViewTreeObserver observer = mDefaultControlLayout.getViewTreeObserver();
48086dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
48186dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            @Override
48286dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            public void onGlobalLayout() {
48386dcb627078ea297c4337ed634fc3fe874e23897Jae Seo                mDefaultControlLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
48486dcb627078ea297c4337ed634fc3fe874e23897Jae Seo                updateLayoutHeightInternal();
48586dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            }
48686dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        });
48792fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang    }
48892fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang
4893fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim    /**
4903fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * Updates the height of views and hide artwork or metadata if space is limited.
4913fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     */
49286dcb627078ea297c4337ed634fc3fe874e23897Jae Seo    private void updateLayoutHeightInternal() {
4932c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        if (mCustomControlView != null) {
4942c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            return;
4952c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
496aaa885dc21bf5f526e1d3897e26ade96e1fae9ccJaewan Kim        updateMediaControlVisibility(isPlaybackControlAvailable());
4972c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        View decorView = getWindow().getDecorView();
4982c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        decorView.measure(
4992c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                MeasureSpec.makeMeasureSpec(getWindow().getAttributes().width, MeasureSpec.EXACTLY),
5002c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                MeasureSpec.UNSPECIFIED);
5012c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int artViewHeight = 0;
5022c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        if (mArtView.getDrawable() instanceof BitmapDrawable) {
5032c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap();
5042c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (art != null) {
5052c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                artViewHeight = getDesiredArtHeight(art.getWidth(), art.getHeight());
5062c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                mArtView.setScaleType(art.getWidth() >= art.getHeight()
5072c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                        ? ImageView.ScaleType.FIT_XY : ImageView.ScaleType.FIT_CENTER);
5082c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
5092c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
5102c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int mainControllerHeight = getMainControllerHeight(isPlaybackControlAvailable());
5112c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int volumeGroupListCount = mVolumeGroupList.getVisibility() == View.VISIBLE
5122c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                ? mVolumeGroupList.getAdapter().getCount() : 0;
513c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        // Scale down volume group list items in landscape mode.
514c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        for (int i = 0; i < volumeGroupListCount; i++) {
515c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim            View item = mVolumeGroupList.getChildAt(i);
516c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim            if (item != null) {
517c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                setLayoutHeight(item, mVolumeGroupListItemHeight);
518c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                setLayoutHeight(item.findViewById(R.id.mr_volume_item_icon),
519c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                        mVolumeGroupListItemIconSize);
520c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim            }
521c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        }
52240181af8431b704013f596a5ac298a06174d4d82Jaewan Kim        int volumeGroupHeight = (volumeGroupListCount == 0) ? 0
523c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                : mVolumeGroupListItemHeight * volumeGroupListCount + mVolumeGroupListPaddingTop;
52419d268075834665bf62567b224dcd3549c92d3c3Jae Seo        volumeGroupHeight = Math.min(volumeGroupHeight, mVolumeGroupListMaxHeight);
52519d268075834665bf62567b224dcd3549c92d3c3Jae Seo
5268367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        int desiredControlLayoutHeight =
5272c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                Math.max(artViewHeight, volumeGroupHeight) + mainControllerHeight;
5282c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        Rect visibleRect = new Rect();
5292c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        decorView.getWindowVisibleDisplayFrame(visibleRect);
5302c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Height of non-control views in decor view.
5312c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // This includes title bar, button bar, and dialog's vertical padding which should be
5322c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // always shown.
5332c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int nonControlViewHeight = decorView.getMeasuredHeight()
5342c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                - mDefaultControlLayout.getMeasuredHeight();
5352c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Maximum allowed height for controls to fit screen.
5362c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int maximumControlViewHeight = visibleRect.height() - nonControlViewHeight;
5372c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
5383fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim        // Show artwork if it fits the screen and expanded volume group list has fewer than 3 items.
5393fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim        if (artViewHeight > 0 && volumeGroupListCount < 3
5408367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim                && desiredControlLayoutHeight <= maximumControlViewHeight) {
5412c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            mArtView.setVisibility(View.VISIBLE);
5422c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            setLayoutHeight(mArtView, artViewHeight);
5432c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        } else {
5442c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            mArtView.setVisibility(View.GONE);
5452c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            artViewHeight = 0;
5468367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim            desiredControlLayoutHeight = volumeGroupHeight + mainControllerHeight;
5472c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
5482c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Show control if it fits the screen
5492c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        if (isPlaybackControlAvailable()
5508367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim                && desiredControlLayoutHeight <= maximumControlViewHeight) {
5512c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            mPlaybackControl.setVisibility(View.VISIBLE);
5522c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        } else {
5532c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            mPlaybackControl.setVisibility(View.GONE);
5542c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
555aaa885dc21bf5f526e1d3897e26ade96e1fae9ccJaewan Kim        updateMediaControlVisibility(mPlaybackControl.getVisibility() == View.VISIBLE);
5562c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        mainControllerHeight = getMainControllerHeight(
5572c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                mPlaybackControl.getVisibility() == View.VISIBLE);
5588367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        desiredControlLayoutHeight =
5592c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                Math.max(artViewHeight, volumeGroupHeight) + mainControllerHeight;
5602c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
5612c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Limit the volume group list height to fit the screen.
5628367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        if (desiredControlLayoutHeight > maximumControlViewHeight) {
5638367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim            volumeGroupHeight -= (desiredControlLayoutHeight - maximumControlViewHeight);
5648367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim            desiredControlLayoutHeight = maximumControlViewHeight;
5652c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
5662c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        setLayoutHeight(mVolumeGroupList, volumeGroupHeight);
5678367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        setLayoutHeight(mDefaultControlLayout, desiredControlLayoutHeight);
5682c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    }
5692c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
5701ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private void updateVolumeControl() {
5711ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        if (!mVolumeSliderTouched) {
5727447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            if (isVolumeControlAvailable(mRoute)) {
5731ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeControl.setVisibility(View.VISIBLE);
5741ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeSlider.setMax(mRoute.getVolumeMax());
5751ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeSlider.setProgress(mRoute.getVolume());
5761ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                if (USE_GROUP) {
5771ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    if (getGroup() == null) {
5781ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        mGroupExpandCollapseButton.setVisibility(View.GONE);
5791ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    } else {
5801ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        mGroupExpandCollapseButton.setVisibility(View.VISIBLE);
5811ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        VolumeGroupAdapter adapter =
5821ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                                (VolumeGroupAdapter) mVolumeGroupList.getAdapter();
5831ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        if (adapter != null) {
5841ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            adapter.notifyDataSetChanged();
5851ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        }
5861ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    }
5871ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
5881ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else {
5891ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeControl.setVisibility(View.GONE);
5901ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
5912c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            updateLayoutHeight();
5927447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim        } else if (mVolumeControl.getVisibility() == View.VISIBLE) {
5937447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            mVolumeSlider.setProgress(mRoute.getVolume());
5947447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            if (mIsGroupExpanded) {
5957447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
5967447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    MediaRouter.RouteInfo route = getGroup().getRouteAt(i);
5977447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    if (isVolumeControlAvailable(route)) {
5987447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                        SeekBar volumeSlider = (SeekBar) mVolumeGroupList.getChildAt(i)
5997447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                                .findViewById(R.id.mr_volume_slider);
6007447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                        volumeSlider.setProgress(route.getVolume());
6017447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    }
6027447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                }
6037447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            }
6041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        }
6051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    }
6061ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
6071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private void updatePlaybackControl() {
6082c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        if (isPlaybackControlAvailable()) {
6091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            CharSequence title = mDescription == null ? null : mDescription.getTitle();
6101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            boolean hasTitle = !TextUtils.isEmpty(title);
6111ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
6121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle();
6131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            boolean hasSubtitle = !TextUtils.isEmpty(subtitle);
6141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
6158fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            boolean showTitle = false;
6168fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            boolean showSubtitle = false;
6178fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            if (mRoute.getPresentationDisplayId()
6188fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) {
6198fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                // The user is currently casting screen.
6208fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_casting_screen);
6218fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
6228fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            } else if (mState == null || mState.getState() == PlaybackStateCompat.STATE_NONE) {
6238fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_no_media_selected);
6248fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
6258fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            } else if (!hasTitle && !hasSubtitle) {
6268fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_no_info_available);
6278fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
6281ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else {
6298fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                if (hasTitle) {
6308fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    mTitleView.setText(title);
6318fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    showTitle = true;
6328fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                }
6338fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                if (hasSubtitle) {
6348fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    mSubtitleView.setText(subtitle);
6358fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    showSubtitle = true;
6368fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                }
6371ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
6388fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            mTitleView.setVisibility(showTitle ? View.VISIBLE : View.GONE);
6398fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            mSubtitleView.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
6408fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang
6411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            if (mState != null) {
6421ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
6431ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
6441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
6451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
6461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
6471ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
6481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                if (isPlaying && supportsPause) {
6491ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setVisibility(View.VISIBLE);
6501ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
6511ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            getContext(), R.attr.mediaRoutePauseDrawable));
6521ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setContentDescription(getContext().getResources()
6531ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            .getText(R.string.mr_controller_pause));
6541ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                } else if (!isPlaying && supportsPlay) {
6551ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setVisibility(View.VISIBLE);
6561ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
6571ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            getContext(), R.attr.mediaRoutePlayDrawable));
6581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setContentDescription(getContext().getResources()
6591ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            .getText(R.string.mr_controller_play));
6601ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                } else {
6611ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setVisibility(View.GONE);
6621ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
6631ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
6641ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        }
6652c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        updateLayoutHeight();
6662b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang    }
6672b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang
6687447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim    private boolean isVolumeControlAvailable(MediaRouter.RouteInfo route) {
6697447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim        return mVolumeControlEnabled && route.getVolumeHandling()
6707447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
671f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
672f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
673be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang    private static void setLayoutHeight(View view, int height) {
674be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        ViewGroup.LayoutParams lp = view.getLayoutParams();
675be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        lp.height = height;
676be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        view.setLayoutParams(lp);
677be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang    }
678be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang
67913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    /**
68013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     * Returns desired art height to fit into controller dialog.
68113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     */
68213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    private int getDesiredArtHeight(int originalWidth, int originalHeight) {
68313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        if (originalWidth >= originalHeight) {
68413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            // For landscape art, fit width to dialog width.
685f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo            return (int) ((float) mDialogContentWidth * originalHeight / originalWidth + 0.5f);
68613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        }
68713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        // For portrait art, fit height to 16:9 ratio case's height.
688f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo        return (int) ((float) mDialogContentWidth * 9 / 16 + 0.5f);
68913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    }
69013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim
69111417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final class MediaRouterCallback extends MediaRouter.Callback {
69211417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
69311417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
69411417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
69511417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
69611417b1cfde8f1749905f2d735623af9214148afJeff Brown
69711417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
69811417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
69911417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
70011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
70111417b1cfde8f1749905f2d735623af9214148afJeff Brown
70211417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
70311417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
70411417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (route == mRoute) {
7051ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                updateVolumeControl();
70694be6100218126ce6a08bf1f56209578500b361fRoboErik            }
70794be6100218126ce6a08bf1f56209578500b361fRoboErik        }
70894be6100218126ce6a08bf1f56209578500b361fRoboErik    }
70994be6100218126ce6a08bf1f56209578500b361fRoboErik
71094be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class MediaControllerCallback extends MediaControllerCompat.Callback {
71194be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
71294be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onSessionDestroyed() {
71394be6100218126ce6a08bf1f56209578500b361fRoboErik            if (mMediaController != null) {
71494be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController.unregisterCallback(mControllerCallback);
71594be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController = null;
71694be6100218126ce6a08bf1f56209578500b361fRoboErik            }
71794be6100218126ce6a08bf1f56209578500b361fRoboErik        }
71894be6100218126ce6a08bf1f56209578500b361fRoboErik
71994be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
72094be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onPlaybackStateChanged(PlaybackStateCompat state) {
72194be6100218126ce6a08bf1f56209578500b361fRoboErik            mState = state;
72294be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
72394be6100218126ce6a08bf1f56209578500b361fRoboErik        }
72494be6100218126ce6a08bf1f56209578500b361fRoboErik
72594be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
72694be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onMetadataChanged(MediaMetadataCompat metadata) {
72794be6100218126ce6a08bf1f56209578500b361fRoboErik            mDescription = metadata == null ? null : metadata.getDescription();
72894be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
72994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
73094be6100218126ce6a08bf1f56209578500b361fRoboErik    }
73194be6100218126ce6a08bf1f56209578500b361fRoboErik
73294be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class ClickListener implements View.OnClickListener {
73394be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
73494be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onClick(View v) {
73594be6100218126ce6a08bf1f56209578500b361fRoboErik            int id = v.getId();
73606991009e52024cbb3dde550988e06149e77a269Jae Seo            if (id == BUTTON_STOP_RES_ID || id == BUTTON_DISCONNECT_RES_ID) {
73794be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mRoute.isSelected()) {
73806991009e52024cbb3dde550988e06149e77a269Jae Seo                    mRouter.unselect(id == BUTTON_STOP_RES_ID ?
73994be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_STOPPED :
74094be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_DISCONNECTED);
74194be6100218126ce6a08bf1f56209578500b361fRoboErik                }
74294be6100218126ce6a08bf1f56209578500b361fRoboErik                dismiss();
7437ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            } else if (id == R.id.mr_control_play_pause) {
74494be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mMediaController != null && mState != null) {
74594be6100218126ce6a08bf1f56209578500b361fRoboErik                    if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) {
74694be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().pause();
74794be6100218126ce6a08bf1f56209578500b361fRoboErik                    } else {
74894be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().play();
74994be6100218126ce6a08bf1f56209578500b361fRoboErik                    }
75094be6100218126ce6a08bf1f56209578500b361fRoboErik                }
7511ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else if (id == R.id.mr_close) {
752b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim                dismiss();
75311417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
75411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
75511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
756005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
757435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private class VolumeChangeListener implements OnSeekBarChangeListener {
758435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        private final Runnable mStopTrackingTouch = new Runnable() {
7596051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            @Override
760435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            public void run() {
761435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                if (mVolumeSliderTouched) {
762435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                    mVolumeSliderTouched = false;
763435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                    updateVolumeControl();
7646051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                }
7656051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
766435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        };
7676051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
768435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
769435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onStartTrackingTouch(SeekBar seekBar) {
770435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            if (mVolumeSliderTouched) {
771435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                mVolumeSlider.removeCallbacks(mStopTrackingTouch);
772435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            } else {
773435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                mVolumeSliderTouched = true;
7746051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
775435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
7766051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
777435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
778435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onStopTrackingTouch(SeekBar seekBar) {
779435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // Defer resetting mVolumeSliderTouched to allow the media route provider
780435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // a little time to settle into its new state and publish the final
781435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // volume update.
782435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
783435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
784435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim
785435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
786435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
787435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            if (fromUser) {
788435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                int tag = (int) seekBar.getTag();
789435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                if (tag == VOLUME_SLIDER_TAG_MASTER) {
790435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                    mRoute.requestSetVolume(progress);
791435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                } else if (tag - VOLUME_SLIDER_TAG_BASE >= 0
792435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                        && tag - VOLUME_SLIDER_TAG_BASE < getGroup().getRouteCount()) {
793435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                    getGroup().getRouteAt(tag - VOLUME_SLIDER_TAG_BASE).requestSetVolume(progress);
794435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                }
7956051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
796435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
797435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    }
798435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim
799435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> {
800435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        final static float DISABLED_ALPHA = .3f;
8016051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
8026051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) {
8036051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            super(context, 0, objects);
8046051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
8056051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
8066051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        @Override
8076051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public View getView(final int position, View convertView, ViewGroup parent) {
8086051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            View v = convertView;
8096051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (v == null) {
8106051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                v = LayoutInflater.from(getContext()).inflate(
8112c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                        R.layout.mr_controller_volume_item, parent, false);
8126051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
81319d268075834665bf62567b224dcd3549c92d3c3Jae Seo
8146051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            MediaRouter.RouteInfo route = getItem(position);
8156051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (route != null) {
8160e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                boolean isEnabled = route.isEnabled();
8170e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
8187ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                TextView routeName = (TextView) v.findViewById(R.id.mr_name);
8190e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setEnabled(isEnabled);
8200e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setText(route.getName());
8216051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
822ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                MediaRouteVolumeSlider volumeSlider =
823ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                        (MediaRouteVolumeSlider) v.findViewById(R.id.mr_volume_slider);
824435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                volumeSlider.setTag(VOLUME_SLIDER_TAG_BASE + position);
825ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                volumeSlider.setShowThumb(isEnabled);
8260e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                if (isEnabled) {
8277447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    if (isVolumeControlAvailable(route)) {
8280e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(route.getVolumeMax());
8290e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(route.getVolume());
830435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                        volumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
831ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                        volumeSlider.setEnabled(true);
8320e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    } else {
8330e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(100);
8340e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(100);
8350e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setEnabled(false);
8360e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    }
8370e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                }
8380e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
8390e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                ImageView volumeItemIcon =
8407ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        (ImageView) v.findViewById(R.id.mr_volume_item_icon);
84177367b4a1871417198d0399d9ad074314c758567Jae Seo                volumeItemIcon.setAlpha(isEnabled ? 255 : (int) (255 * DISABLED_ALPHA));
8426051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
8436051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return v;
8446051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
8456051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
8466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
847005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> {
8488bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        final Bitmap mIconBitmap;
8498bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        final Uri mIconUri;
8508bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        int mBackgroundColor;
8518bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
8528bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        FetchArtTask() {
8538bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            mIconBitmap = mDescription == null ? null : mDescription.getIconBitmap();
8548bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            mIconUri = mDescription == null ? null : mDescription.getIconUri();
8558bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        }
8568bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
8578bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        @Override
8588bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        protected void onPreExecute() {
8598bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            if (mArtIconBitmap == mIconBitmap && mArtIconUri == mIconUri) {
8608bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                // Already handled the current art.
8618bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                cancel(true);
8628bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            }
8638bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        }
864005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
865005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
866005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        protected Bitmap doInBackground(Void... arg) {
86713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            Bitmap art = null;
8688bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            if (mIconBitmap != null) {
8698bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                art = mIconBitmap;
8708bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            } else if (mIconUri != null) {
8718bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                String scheme = mIconUri.getScheme();
872005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                if (!(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
873005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        || ContentResolver.SCHEME_CONTENT.equals(scheme)
874005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        || ContentResolver.SCHEME_FILE.equals(scheme))) {
875005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    Log.w(TAG, "Icon Uri should point to local resources.");
876005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    return null;
877005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                }
878005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                BufferedInputStream stream = null;
879005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                try {
880005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    stream = new BufferedInputStream(
8818bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                            getContext().getContentResolver().openInputStream(mIconUri));
882005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
88313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Query art size.
884005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.Options options = new BitmapFactory.Options();
885005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = true;
886005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.decodeStream(stream, null, options);
88713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    if (options.outWidth == 0 || options.outHeight == 0) {
88813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                        return null;
88913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    }
89013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Rewind the stream in order to restart art decoding.
891005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    try {
892005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.reset();
893005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    } catch (IOException e) {
894005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        // Failed to rewind the stream, try to reopen it.
895005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.close();
896005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream = new BufferedInputStream(getContext().getContentResolver()
8978bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                                .openInputStream(mIconUri));
898005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
89913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Calculate required size to decode the art and possibly resize it.
900005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = false;
90113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight);
90213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int ratio = options.outHeight / reqHeight;
903005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio));
904005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (isCancelled()) {
905005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        return null;
906005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
90713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    art = BitmapFactory.decodeStream(stream, null, options);
908005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } catch (IOException e){
9098bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                    Log.w(TAG, "Unable to open: " + mIconUri, e);
910005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } finally {
911005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (stream != null) {
912005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        try {
913005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                            stream.close();
914005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        } catch (IOException e) {
915005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        }
916005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
917005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                }
918005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
919145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim            if (art != null && art.getWidth() < art.getHeight()) {
920145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                // Portrait art requires background color.
921145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                Palette palette = new Palette.Builder(art).maximumColorCount(1).generate();
922be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang                mBackgroundColor = palette.getSwatches().isEmpty()
923145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                        ? 0 : palette.getSwatches().get(0).getRgb();
924005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
92513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            return art;
926005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
927005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
928005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
929005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        protected void onCancelled() {
930005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = null;
931005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
932005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
933005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
93413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        protected void onPostExecute(Bitmap art) {
935005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = null;
9368bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            if (mArtIconBitmap != mIconBitmap || mArtIconUri != mIconUri) {
9378bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtIconBitmap = mIconBitmap;
9388bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtIconUri = mIconUri;
9398bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
9408bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtView.setImageBitmap(art);
9418bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtView.setBackgroundColor(mBackgroundColor);
9422c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                updateLayoutHeight();
9438bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            }
944005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
945005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    }
9466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo}
947