MediaRouteControllerDialog.java revision f291fbba316ca92573d84dbe37e48e9d83181318
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
21f291fbba316ca92573d84dbe37e48e9d83181318Jae Seoimport android.app.PendingIntent;
22005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.content.ContentResolver;
2311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context;
24c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kimimport android.content.res.Resources;
25005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap;
26005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory;
272c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kimimport android.graphics.Rect;
2813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.graphics.drawable.BitmapDrawable;
29005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.net.Uri;
30005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.os.AsyncTask;
3111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle;
3294be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException;
3394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat;
3494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat;
3594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaControllerCompat;
3694be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat;
3794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat;
38ee7ae661b02471fe598566b1e90adbacda240b0bJae Seoimport android.support.v4.view.accessibility.AccessibilityEventCompat;
39005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.support.v7.graphics.Palette;
40f0fddecaadb2fc0cc6c8743905b6c78e665f0ba0Insun Kangimport android.support.v7.media.MediaControlIntent;
4111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouteSelector;
4211417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.media.MediaRouter;
4311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.support.v7.mediarouter.R;
4494be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils;
4594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log;
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;
52ee7ae661b02471fe598566b1e90adbacda240b0bJae Seoimport android.view.accessibility.AccessibilityEvent;
53ee7ae661b02471fe598566b1e90adbacda240b0bJae Seoimport android.view.accessibility.AccessibilityManager;
5404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kangimport android.view.animation.Animation;
5504b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kangimport android.view.animation.Transformation;
566051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter;
5711417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button;
5811417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout;
5994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton;
6094be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView;
61f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout;
626051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ListView;
637ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport android.widget.RelativeLayout;
64f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar;
6594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView;
6611417b1cfde8f1749905f2d735623af9214148afJeff Brown
67005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream;
68005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException;
696051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List;
70005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
7111417b1cfde8f1749905f2d735623af9214148afJeff Brown/**
7211417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}.
7311417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p>
7411417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route.
7511417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p>
7611417b1cfde8f1749905f2d735623af9214148afJeff Brown *
7711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton
7811417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider
7911417b1cfde8f1749905f2d735623af9214148afJeff Brown */
8089530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog {
8111417b1cfde8f1749905f2d735623af9214148afJeff Brown    private static final String TAG = "MediaRouteControllerDialog";
8211417b1cfde8f1749905f2d735623af9214148afJeff Brown
83f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // Time to wait before updating the volume when the user lets go of the seek bar
84f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // to allow the route provider time to propagate the change and publish a new
85f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // route descriptor.
86f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private static final int VOLUME_UPDATE_DELAY_MILLIS = 250;
87435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private static final int VOLUME_SLIDER_TAG_MASTER = 0;
88d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo    private static final int VOLUME_SLIDER_TAG_GROUP_BASE = 100;
89f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
9006991009e52024cbb3dde550988e06149e77a269Jae Seo    private static final int BUTTON_NEUTRAL_RES_ID = android.R.id.button3;
9106991009e52024cbb3dde550988e06149e77a269Jae Seo    private static final int BUTTON_DISCONNECT_RES_ID = android.R.id.button2;
9206991009e52024cbb3dde550988e06149e77a269Jae Seo    private static final int BUTTON_STOP_RES_ID = android.R.id.button1;
9306991009e52024cbb3dde550988e06149e77a269Jae Seo
9411417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter mRouter;
9511417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouterCallback mCallback;
9611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouter.RouteInfo mRoute;
9711417b1cfde8f1749905f2d735623af9214148afJeff Brown
984c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang    private Context mContext;
99eff7719415542ba819054863b0995f07742a7a8aJeff Brown    private boolean mCreated;
100e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private boolean mAttachedToWindow;
101e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo
102f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo    private int mDialogContentWidth;
10311417b1cfde8f1749905f2d735623af9214148afJeff Brown
1047ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private View mCustomControlView;
10511417b1cfde8f1749905f2d735623af9214148afJeff Brown
10611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private Button mDisconnectButton;
10794be6100218126ce6a08bf1f56209578500b361fRoboErik    private Button mStopCastingButton;
1081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private ImageButton mPlayPauseButton;
109b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim    private ImageButton mCloseButton;
110328f1006c17ddeb3eb563580bcd6638e1cfb4320Jaewan Kim    private MediaRouteExpandCollapseButton mGroupExpandCollapseButton;
11194be6100218126ce6a08bf1f56209578500b361fRoboErik
112c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private FrameLayout mExpandableAreaLayout;
113c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private LinearLayout mDialogAreaLayout;
1142b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang    private FrameLayout mDefaultControlLayout;
115c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private FrameLayout mCustomControlLayout;
11694be6100218126ce6a08bf1f56209578500b361fRoboErik    private ImageView mArtView;
1171ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private TextView mTitleView;
1181ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private TextView mSubtitleView;
1197ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private TextView mRouteNameTextView;
12094be6100218126ce6a08bf1f56209578500b361fRoboErik
121f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private boolean mVolumeControlEnabled = true;
12204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    // Layout for media controllers including play/pause button and the main volume slider.
1232c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    private LinearLayout mMediaMainControlLayout;
12470cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private RelativeLayout mPlaybackControlLayout;
12570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private LinearLayout mVolumeControlLayout;
1261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private View mDividerView;
1271ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
1286051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private ListView mVolumeGroupList;
1291ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private SeekBar mVolumeSlider;
130435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private VolumeChangeListener mVolumeChangeListener;
1311ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private boolean mVolumeSliderTouched;
132c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListItemIconSize;
133c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListItemHeight;
134c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListMaxHeight;
135c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private final int mVolumeGroupListPaddingTop;
136f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
13794be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCompat mMediaController;
13894be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaControllerCallback mControllerCallback;
13994be6100218126ce6a08bf1f56209578500b361fRoboErik    private PlaybackStateCompat mState;
14094be6100218126ce6a08bf1f56209578500b361fRoboErik    private MediaDescriptionCompat mDescription;
14194be6100218126ce6a08bf1f56209578500b361fRoboErik
142005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    private FetchArtTask mFetchArtTask;
1438bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo    private Bitmap mArtIconBitmap;
1448bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo    private Uri mArtIconUri;
1452b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang    private boolean mIsGroupExpanded;
14604b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    private boolean mIsGroupListAnimationNeeded;
14704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    private int mGroupListAnimationDurationMs;
14811417b1cfde8f1749905f2d735623af9214148afJeff Brown
149ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo    private final AccessibilityManager mAccessibilityManager;
150ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo
15111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context) {
15211417b1cfde8f1749905f2d735623af9214148afJeff Brown        this(context, 0);
15311417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
15411417b1cfde8f1749905f2d735623af9214148afJeff Brown
15511417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context, int theme) {
15694be6100218126ce6a08bf1f56209578500b361fRoboErik        super(MediaRouterThemeHelper.createThemedContext(context), theme);
1574c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        mContext = getContext();
15811417b1cfde8f1749905f2d735623af9214148afJeff Brown
15994be6100218126ce6a08bf1f56209578500b361fRoboErik        mControllerCallback = new MediaControllerCallback();
16011417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter = MediaRouter.getInstance(context);
16111417b1cfde8f1749905f2d735623af9214148afJeff Brown        mCallback = new MediaRouterCallback();
16211417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRoute = mRouter.getSelectedRoute();
163e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
164c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListPaddingTop = context.getResources().getDimensionPixelSize(
165c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_padding_top);
166ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo        mAccessibilityManager =
167ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
16811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
16911417b1cfde8f1749905f2d735623af9214148afJeff Brown
17011417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
17111417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the route that this dialog is controlling.
17211417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
17311417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouter.RouteInfo getRoute() {
17411417b1cfde8f1749905f2d735623af9214148afJeff Brown        return mRoute;
17511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
17611417b1cfde8f1749905f2d735623af9214148afJeff Brown
1776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private MediaRouter.RouteGroup getGroup() {
1786051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        if (mRoute instanceof MediaRouter.RouteGroup) {
1796051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return (MediaRouter.RouteGroup) mRoute;
1806051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
1816051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        return null;
1826051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
1836051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
18411417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
18556d9fd2c2746f50e6a31e24b19e8671bba31a842Dongwon Kang     * Provides the subclass an opportunity to create a view that will replace the default media
18656d9fd2c2746f50e6a31e24b19e8671bba31a842Dongwon Kang     * controls for the currently playing content.
18711417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
18811417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @param savedInstanceState The dialog's saved instance state.
18911417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
19011417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
19111417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View onCreateMediaControlView(Bundle savedInstanceState) {
19211417b1cfde8f1749905f2d735623af9214148afJeff Brown        return null;
19311417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
19411417b1cfde8f1749905f2d735623af9214148afJeff Brown
19511417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
19611417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}.
19711417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
19811417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
19911417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
20011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View getMediaControlView() {
2017ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        return mCustomControlView;
20211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
20311417b1cfde8f1749905f2d735623af9214148afJeff Brown
204eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
205f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Sets whether to enable the volume slider and volume control using the volume keys
206f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
207f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * <p>
208f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * The default value is true.
209f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * </p>
210f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
211f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public void setVolumeControlEnabled(boolean enable) {
212f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        if (mVolumeControlEnabled != enable) {
213f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            mVolumeControlEnabled = enable;
214f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            if (mCreated) {
21570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                updateVolumeControlLayout();
216f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            }
217f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        }
218f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
219f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
220f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
221f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Returns whether to enable the volume slider and volume control using the volume keys
222f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
223f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
224f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public boolean isVolumeControlEnabled() {
225f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        return mVolumeControlEnabled;
226f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
227f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
228f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
22994be6100218126ce6a08bf1f56209578500b361fRoboErik     * Set the session to use for metadata and transport controls. The dialog
23094be6100218126ce6a08bf1f56209578500b361fRoboErik     * will listen to changes on this session and update the UI automatically in
23194be6100218126ce6a08bf1f56209578500b361fRoboErik     * response to changes.
23294be6100218126ce6a08bf1f56209578500b361fRoboErik     *
23394be6100218126ce6a08bf1f56209578500b361fRoboErik     * @param sessionToken The token for the session to use.
234eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
235e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private void setMediaSession(MediaSessionCompat.Token sessionToken) {
23694be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
23794be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.unregisterCallback(mControllerCallback);
23894be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = null;
23994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
24094be6100218126ce6a08bf1f56209578500b361fRoboErik        if (sessionToken == null) {
24194be6100218126ce6a08bf1f56209578500b361fRoboErik            return;
24294be6100218126ce6a08bf1f56209578500b361fRoboErik        }
243e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        if (!mAttachedToWindow) {
244e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            return;
245e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
24694be6100218126ce6a08bf1f56209578500b361fRoboErik        try {
2474c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang            mMediaController = new MediaControllerCompat(mContext, sessionToken);
24894be6100218126ce6a08bf1f56209578500b361fRoboErik        } catch (RemoteException e) {
24994be6100218126ce6a08bf1f56209578500b361fRoboErik            Log.e(TAG, "Error creating media controller in setMediaSession.", e);
25094be6100218126ce6a08bf1f56209578500b361fRoboErik        }
25194be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
25294be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.registerCallback(mControllerCallback);
253eff7719415542ba819054863b0995f07742a7a8aJeff Brown        }
25494be6100218126ce6a08bf1f56209578500b361fRoboErik        MediaMetadataCompat metadata = mMediaController == null ? null
25594be6100218126ce6a08bf1f56209578500b361fRoboErik                : mMediaController.getMetadata();
25694be6100218126ce6a08bf1f56209578500b361fRoboErik        mDescription = metadata == null ? null : metadata.getDescription();
25794be6100218126ce6a08bf1f56209578500b361fRoboErik        mState = mMediaController == null ? null : mMediaController.getPlaybackState();
25894be6100218126ce6a08bf1f56209578500b361fRoboErik        update();
259eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
260eff7719415542ba819054863b0995f07742a7a8aJeff Brown
261eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
26275dbda46b4ca20861e9d382b1662b3c34d20da8aInsun Kang     * Gets the session to use for metadata and transport controls.
26394be6100218126ce6a08bf1f56209578500b361fRoboErik     *
26475dbda46b4ca20861e9d382b1662b3c34d20da8aInsun Kang     * @return The token for the session to use or null if none.
265eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
26694be6100218126ce6a08bf1f56209578500b361fRoboErik    public MediaSessionCompat.Token getMediaSession() {
26794be6100218126ce6a08bf1f56209578500b361fRoboErik        return mMediaController == null ? null : mMediaController.getSessionToken();
268eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
269eff7719415542ba819054863b0995f07742a7a8aJeff Brown
27011417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
27111417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void onCreate(Bundle savedInstanceState) {
27211417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onCreate(savedInstanceState);
27311417b1cfde8f1749905f2d735623af9214148afJeff Brown
274c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        getWindow().setBackgroundDrawableResource(android.R.color.transparent);
275a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim        setContentView(R.layout.mr_controller_material_dialog_b);
276f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo
27706991009e52024cbb3dde550988e06149e77a269Jae Seo        // Remove the neutral button.
27806991009e52024cbb3dde550988e06149e77a269Jae Seo        findViewById(BUTTON_NEUTRAL_RES_ID).setVisibility(View.GONE);
27906991009e52024cbb3dde550988e06149e77a269Jae Seo
28094be6100218126ce6a08bf1f56209578500b361fRoboErik        ClickListener listener = new ClickListener();
281d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown
282c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mExpandableAreaLayout = (FrameLayout) findViewById(R.id.mr_expandable_area);
283c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mExpandableAreaLayout.setOnClickListener(new View.OnClickListener() {
284c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            @Override
285c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            public void onClick(View v) {
286c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                dismiss();
287c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            }
288c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        });
289c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mDialogAreaLayout = (LinearLayout) findViewById(R.id.mr_dialog_area);
290c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mDialogAreaLayout.setOnClickListener(new View.OnClickListener() {
291c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            @Override
292c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            public void onClick(View v) {
293c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                // Eat unhandled touch events.
294c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            }
295c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        });
2966f6fdaf79cd74810b2b96514c6914ae1dbe6c5f0Jae Seo        int color = MediaRouterThemeHelper.getButtonTextColor(mContext);
29706991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton = (Button) findViewById(BUTTON_DISCONNECT_RES_ID);
29806991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton.setText(R.string.mr_controller_disconnect);
2996f6fdaf79cd74810b2b96514c6914ae1dbe6c5f0Jae Seo        mDisconnectButton.setTextColor(color);
30094be6100218126ce6a08bf1f56209578500b361fRoboErik        mDisconnectButton.setOnClickListener(listener);
30111417b1cfde8f1749905f2d735623af9214148afJeff Brown
30206991009e52024cbb3dde550988e06149e77a269Jae Seo        mStopCastingButton = (Button) findViewById(BUTTON_STOP_RES_ID);
30306991009e52024cbb3dde550988e06149e77a269Jae Seo        mStopCastingButton.setText(R.string.mr_controller_stop);
3046f6fdaf79cd74810b2b96514c6914ae1dbe6c5f0Jae Seo        mStopCastingButton.setTextColor(color);
30594be6100218126ce6a08bf1f56209578500b361fRoboErik        mStopCastingButton.setOnClickListener(listener);
30611417b1cfde8f1749905f2d735623af9214148afJeff Brown
3071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mRouteNameTextView = (TextView) findViewById(R.id.mr_name);
3081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mCloseButton = (ImageButton) findViewById(R.id.mr_close);
309b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim        mCloseButton.setOnClickListener(listener);
3101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mCustomControlLayout = (FrameLayout) findViewById(R.id.mr_custom_control);
3112b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang        mDefaultControlLayout = (FrameLayout) findViewById(R.id.mr_default_control);
312f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo
313f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        // Start the session activity when a content item (album art, title or subtitle) is clicked.
314f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        View.OnClickListener onClickListener = new View.OnClickListener() {
315f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo            @Override
316f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo            public void onClick(View v) {
317f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                if (mMediaController != null) {
318f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                    PendingIntent pi = mMediaController.getSessionActivity();
319f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                    if (pi != null) {
320f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                        try {
321f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                            pi.send();
322f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                        } catch (PendingIntent.CanceledException e) {
323f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                            Log.e(TAG, pi + " was not sent, it had been canceled.");
324f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                        }
325f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                    }
326f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                }
327f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                dismiss();
328f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo            }
329f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        };
3307ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mArtView = (ImageView) findViewById(R.id.mr_art);
331f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        mArtView.setOnClickListener(onClickListener);
332f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        findViewById(R.id.mr_control_title_container).setOnClickListener(onClickListener);
3336051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
3342c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        mMediaMainControlLayout = (LinearLayout) findViewById(R.id.mr_media_main_control);
3351ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mDividerView = findViewById(R.id.mr_control_divider);
3361ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
33770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        mPlaybackControlLayout = (RelativeLayout) findViewById(R.id.mr_playback_control);
3381ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mTitleView = (TextView) findViewById(R.id.mr_control_title);
3391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mSubtitleView = (TextView) findViewById(R.id.mr_control_subtitle);
3401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mPlayPauseButton = (ImageButton) findViewById(R.id.mr_control_play_pause);
3411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mPlayPauseButton.setOnClickListener(listener);
3421ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
34370cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        mVolumeControlLayout = (LinearLayout) findViewById(R.id.mr_volume_control);
3441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mVolumeSlider = (SeekBar) findViewById(R.id.mr_volume_slider);
345435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeSlider.setTag(VOLUME_SLIDER_TAG_MASTER);
346435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeChangeListener = new VolumeChangeListener();
347435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
3481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
349328f1006c17ddeb3eb563580bcd6638e1cfb4320Jaewan Kim        mVolumeGroupList = (ListView) findViewById(R.id.mr_volume_group_list);
350d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo        MediaRouterThemeHelper.setMediaControlsBackgroundColor(mContext,
351d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                mMediaMainControlLayout, mVolumeGroupList, getGroup() != null);
352d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo        MediaRouterThemeHelper.setVolumeSliderColor(mContext,
353d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                (MediaRouteVolumeSlider) mVolumeSlider, mMediaMainControlLayout);
354d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo
355328f1006c17ddeb3eb563580bcd6638e1cfb4320Jaewan Kim        mGroupExpandCollapseButton =
356328f1006c17ddeb3eb563580bcd6638e1cfb4320Jaewan Kim                (MediaRouteExpandCollapseButton) findViewById(R.id.mr_group_expand_collapse);
3571ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() {
3581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            @Override
3591ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            public void onClick(View v) {
3602b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang                mIsGroupExpanded = !mIsGroupExpanded;
3612b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang                if (mIsGroupExpanded) {
3621ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mVolumeGroupList.setVisibility(View.VISIBLE);
3631ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mVolumeGroupList.setAdapter(
3644c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                            new VolumeGroupAdapter(mContext, getGroup().getRoutes()));
3651ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                } else {
36604b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang                    // Request layout to update UI based on {@code mIsGroupExpanded}.
36704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang                    mDefaultControlLayout.requestLayout();
3681ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
36904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang                mIsGroupListAnimationNeeded = true;
3702c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                updateLayoutHeight();
3711ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
3721ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        });
3734c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        mGroupListAnimationDurationMs = mContext.getResources().getInteger(
374c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                R.integer.mr_controller_volume_group_list_animation_duration_ms);
37511417b1cfde8f1749905f2d735623af9214148afJeff Brown
3767ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mCustomControlView = onCreateMediaControlView(savedInstanceState);
3777ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        if (mCustomControlView != null) {
3781ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            mCustomControlLayout.addView(mCustomControlView);
3791ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            mCustomControlLayout.setVisibility(View.VISIBLE);
38011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
38186a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo        mCreated = true;
382d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        updateLayout();
383d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    }
384d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
385d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    /**
386d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo     * Sets the width of the dialog. Also called when configuration changes.
387d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo     */
388d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    void updateLayout() {
3894c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        int width = MediaRouteDialogHelper.getDialogWidth(mContext);
390d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        getWindow().setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT);
391d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
392d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        View decorView = getWindow().getDecorView();
393d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        mDialogContentWidth = width - decorView.getPaddingLeft() - decorView.getPaddingRight();
394d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
3954c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        Resources res = mContext.getResources();
396c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListItemIconSize = res.getDimensionPixelSize(
397c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_item_icon_size);
398c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListItemHeight = res.getDimensionPixelSize(
399c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_item_height);
400c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListMaxHeight = res.getDimensionPixelSize(
401c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_max_height);
402c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim
403c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        // Ensure the mArtView is updated.
404c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        mArtIconBitmap = null;
405c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        mArtIconUri = null;
4067ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        update();
40711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
40811417b1cfde8f1749905f2d735623af9214148afJeff Brown
40911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
41011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onAttachedToWindow() {
41111417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onAttachedToWindow();
412e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = true;
41311417b1cfde8f1749905f2d735623af9214148afJeff Brown
41411417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback,
41511417b1cfde8f1749905f2d735623af9214148afJeff Brown                MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
416e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
41711417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
41811417b1cfde8f1749905f2d735623af9214148afJeff Brown
41911417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
42011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onDetachedFromWindow() {
42111417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.removeCallback(mCallback);
422e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(null);
423e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = false;
42411417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onDetachedFromWindow();
42511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
42611417b1cfde8f1749905f2d735623af9214148afJeff Brown
42711417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
42811417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyDown(int keyCode, KeyEvent event) {
429ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
430ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
431ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1);
432ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
43311417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
43411417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyDown(keyCode, event);
43511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
43611417b1cfde8f1749905f2d735623af9214148afJeff Brown
43711417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
43811417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyUp(int keyCode, KeyEvent event) {
439ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
440ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
441ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
44211417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
44311417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyUp(keyCode, event);
44411417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
44511417b1cfde8f1749905f2d735623af9214148afJeff Brown
4467ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private void update() {
44711417b1cfde8f1749905f2d735623af9214148afJeff Brown        if (!mRoute.isSelected() || mRoute.isDefault()) {
44811417b1cfde8f1749905f2d735623af9214148afJeff Brown            dismiss();
4497ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
45011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
45194be6100218126ce6a08bf1f56209578500b361fRoboErik        if (!mCreated) {
4527ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
45394be6100218126ce6a08bf1f56209578500b361fRoboErik        }
4542ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown
4557ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mRouteNameTextView.setText(mRoute.getName());
45606991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE);
45794be6100218126ce6a08bf1f56209578500b361fRoboErik
4587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        if (mCustomControlView == null) {
459005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            if (mFetchArtTask != null) {
460005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                mFetchArtTask.cancel(true);
46166937fc7dfe22c8c505bf735781d1f5b62f08e34Dongwon Kang            }
462005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = new FetchArtTask();
463005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask.execute();
464f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        }
46570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updateVolumeControlLayout();
46670cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updatePlaybackControlLayout();
4671ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    }
4681ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
46970cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private boolean canShowPlaybackControlLayout() {
470f0fddecaadb2fc0cc6c8743905b6c78e665f0ba0Insun Kang        // If a route does not support remote playback, it means that the route is dedicated for
4714b2b14c1609c1a5c822f3ea7426c5ee7f5379e0cInsun Kang        // audio or video streaming such as A2DP speaker or headset. In this case, the route
472f0fddecaadb2fc0cc6c8743905b6c78e665f0ba0Insun Kang        // provider does not provide any playback information such as metadata or playback status.
4734b2b14c1609c1a5c822f3ea7426c5ee7f5379e0cInsun Kang        // But, for live video, playback control UI shows a message that the screen is being
474f0fddecaadb2fc0cc6c8743905b6c78e665f0ba0Insun Kang        // mirrored, while it does not show anything for live audio.
475f0fddecaadb2fc0cc6c8743905b6c78e665f0ba0Insun Kang        return mCustomControlView == null && (mDescription != null || mState != null)
476f0fddecaadb2fc0cc6c8743905b6c78e665f0ba0Insun Kang                && (mRoute.supportsControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
477f0fddecaadb2fc0cc6c8743905b6c78e665f0ba0Insun Kang                || mRoute.supportsControlCategory(MediaControlIntent.CATEGORY_LIVE_VIDEO));
478f043da1f3472ec6f7f4cfe59574aa036b4acdc61Insun Kang    }
479f043da1f3472ec6f7f4cfe59574aa036b4acdc61Insun Kang
4803fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim    /**
4813fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * Returns the height of main media controller which includes playback control and master
4823fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * volume control.
4833fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     */
4842c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    private int getMainControllerHeight(boolean showPlaybackControl) {
4852c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int height = 0;
48670cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        if (showPlaybackControl || mVolumeControlLayout.getVisibility() == View.VISIBLE) {
4872c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            height += mMediaMainControlLayout.getPaddingTop()
4882c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                    + mMediaMainControlLayout.getPaddingBottom();
4892c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (showPlaybackControl) {
49070cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                height +=  mPlaybackControlLayout.getMeasuredHeight();
4912c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
49270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            if (mVolumeControlLayout.getVisibility() == View.VISIBLE) {
49370cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                height += mVolumeControlLayout.getMeasuredHeight();
4942c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
49570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            if (showPlaybackControl && mVolumeControlLayout.getVisibility() == View.VISIBLE) {
4962c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                height += mDividerView.getMeasuredHeight();
4972c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
4982c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
4992c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        return height;
5002c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    }
5012c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
50270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private void updateMediaControlVisibility(boolean canShowPlaybackControlLayout) {
50392fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        // TODO: Update the top and bottom padding of the control layout according to the display
50492fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        // height.
50570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        mDividerView.setVisibility((mVolumeControlLayout.getVisibility() == View.VISIBLE
50670cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                && canShowPlaybackControlLayout) ? View.VISIBLE : View.GONE);
50770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        mMediaMainControlLayout.setVisibility((mVolumeControlLayout.getVisibility() == View.GONE
50870cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                && !canShowPlaybackControlLayout) ? View.GONE : View.VISIBLE);
50986dcb627078ea297c4337ed634fc3fe874e23897Jae Seo    }
51086dcb627078ea297c4337ed634fc3fe874e23897Jae Seo
51186dcb627078ea297c4337ed634fc3fe874e23897Jae Seo    private void updateLayoutHeight() {
51286dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // We need to defer the update until the first layout has occurred, as we don't yet know the
51386dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // overall visible display size in which the window this view is attached to has been
51486dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // positioned in.
51586dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        ViewTreeObserver observer = mDefaultControlLayout.getViewTreeObserver();
51686dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
51786dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            @Override
51886dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            public void onGlobalLayout() {
51986dcb627078ea297c4337ed634fc3fe874e23897Jae Seo                mDefaultControlLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
52086dcb627078ea297c4337ed634fc3fe874e23897Jae Seo                updateLayoutHeightInternal();
52186dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            }
52286dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        });
52392fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang    }
52492fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang
5253fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim    /**
5263fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * Updates the height of views and hide artwork or metadata if space is limited.
5273fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     */
52886dcb627078ea297c4337ed634fc3fe874e23897Jae Seo    private void updateLayoutHeightInternal() {
52904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        // Measure the size of widgets and get the height of main components.
530c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        int oldHeight = getLayoutHeight(mMediaMainControlLayout);
531c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        setLayoutHeight(mMediaMainControlLayout, ViewGroup.LayoutParams.FILL_PARENT);
53270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updateMediaControlVisibility(canShowPlaybackControlLayout());
5332c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        View decorView = getWindow().getDecorView();
5342c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        decorView.measure(
5352c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                MeasureSpec.makeMeasureSpec(getWindow().getAttributes().width, MeasureSpec.EXACTLY),
5362c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                MeasureSpec.UNSPECIFIED);
537c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        setLayoutHeight(mMediaMainControlLayout, oldHeight);
5382c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int artViewHeight = 0;
539fdafcdb0e1c10c02e17085d35ae2861362809e95Dongwon Kang        if (mCustomControlView == null && mArtView.getDrawable() instanceof BitmapDrawable) {
5402c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap();
5412c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (art != null) {
5422c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                artViewHeight = getDesiredArtHeight(art.getWidth(), art.getHeight());
5432c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                mArtView.setScaleType(art.getWidth() >= art.getHeight()
5442c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                        ? ImageView.ScaleType.FIT_XY : ImageView.ScaleType.FIT_CENTER);
5452c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
5462c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
54770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        int mainControllerHeight = getMainControllerHeight(canShowPlaybackControlLayout());
54804b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        int volumeGroupListCount = mVolumeGroupList.getAdapter() != null
5492c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                ? mVolumeGroupList.getAdapter().getCount() : 0;
550c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        // Scale down volume group list items in landscape mode.
551d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        for (int i = 0; i < mVolumeGroupList.getChildCount(); i++) {
552d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim            updateVolumeGroupItemHeight(mVolumeGroupList.getChildAt(i));
553c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        }
55404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        int expandedGroupListHeight = mVolumeGroupListItemHeight * volumeGroupListCount;
55504b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        if (volumeGroupListCount > 0) {
55604b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            expandedGroupListHeight += mVolumeGroupListPaddingTop;
55704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        }
55804b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        expandedGroupListHeight = Math.min(expandedGroupListHeight, mVolumeGroupListMaxHeight);
55904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        int visibleGroupListHeight = mIsGroupExpanded ? expandedGroupListHeight : 0;
56019d268075834665bf62567b224dcd3549c92d3c3Jae Seo
5618367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        int desiredControlLayoutHeight =
56204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang                Math.max(artViewHeight, visibleGroupListHeight) + mainControllerHeight;
5632c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        Rect visibleRect = new Rect();
5642c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        decorView.getWindowVisibleDisplayFrame(visibleRect);
5652c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Height of non-control views in decor view.
5662c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // This includes title bar, button bar, and dialog's vertical padding which should be
5672c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // always shown.
568c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        int nonControlViewHeight = mDialogAreaLayout.getMeasuredHeight()
5692c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                - mDefaultControlLayout.getMeasuredHeight();
5702c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Maximum allowed height for controls to fit screen.
5712c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int maximumControlViewHeight = visibleRect.height() - nonControlViewHeight;
5722c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
57304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        // Show artwork if it fits the screen.
574fdafcdb0e1c10c02e17085d35ae2861362809e95Dongwon Kang        if (mCustomControlView == null && artViewHeight > 0
575fdafcdb0e1c10c02e17085d35ae2861362809e95Dongwon Kang                && desiredControlLayoutHeight <= maximumControlViewHeight) {
5762c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            mArtView.setVisibility(View.VISIBLE);
5772c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            setLayoutHeight(mArtView, artViewHeight);
5782c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        } else {
579c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            if (getLayoutHeight(mVolumeGroupList) + mMediaMainControlLayout.getMeasuredHeight()
580c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                    >= mDefaultControlLayout.getMeasuredHeight()) {
581c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                mArtView.setVisibility(View.GONE);
582c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            }
5832c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            artViewHeight = 0;
58404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            desiredControlLayoutHeight = visibleGroupListHeight + mainControllerHeight;
5852c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
586c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        // Show the playback control if it fits the screen.
58770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        if (canShowPlaybackControlLayout()
588f043da1f3472ec6f7f4cfe59574aa036b4acdc61Insun Kang                && desiredControlLayoutHeight <= maximumControlViewHeight) {
58970cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            mPlaybackControlLayout.setVisibility(View.VISIBLE);
5902c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        } else {
59170cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            mPlaybackControlLayout.setVisibility(View.GONE);
5922c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
59370cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updateMediaControlVisibility(mPlaybackControlLayout.getVisibility() == View.VISIBLE);
5942c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        mainControllerHeight = getMainControllerHeight(
59570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                mPlaybackControlLayout.getVisibility() == View.VISIBLE);
5968367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        desiredControlLayoutHeight =
59704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang                Math.max(artViewHeight, visibleGroupListHeight) + mainControllerHeight;
5982c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
5992c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Limit the volume group list height to fit the screen.
6008367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        if (desiredControlLayoutHeight > maximumControlViewHeight) {
60104b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            visibleGroupListHeight -= (desiredControlLayoutHeight - maximumControlViewHeight);
6028367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim            desiredControlLayoutHeight = maximumControlViewHeight;
6032c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
604c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        // Update the layouts with the computed heights.
605c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mMediaMainControlLayout.clearAnimation();
606c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mVolumeGroupList.clearAnimation();
607c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mDefaultControlLayout.clearAnimation();
608c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        if (mIsGroupListAnimationNeeded) {
609c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            animateLayoutHeight(mMediaMainControlLayout, mainControllerHeight);
610c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            animateLayoutHeight(mVolumeGroupList, visibleGroupListHeight);
611c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            animateLayoutHeight(mDefaultControlLayout, desiredControlLayoutHeight);
61204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        } else {
613c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            setLayoutHeight(mMediaMainControlLayout, mainControllerHeight);
61404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            setLayoutHeight(mVolumeGroupList, visibleGroupListHeight);
615c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            setLayoutHeight(mDefaultControlLayout, desiredControlLayoutHeight);
61604b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        }
61704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        mIsGroupListAnimationNeeded = false;
618c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        // Maximize the window size with a transparent layout in advance for smooth animation.
619c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        setLayoutHeight(mExpandableAreaLayout, visibleRect.height());
62004b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    }
62104b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang
622d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim    private void updateVolumeGroupItemHeight(View item) {
623d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        setLayoutHeight(item, mVolumeGroupListItemHeight);
624d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        View icon = item.findViewById(R.id.mr_volume_item_icon);
625d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        ViewGroup.LayoutParams lp = icon.getLayoutParams();
626d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        lp.width = mVolumeGroupListItemIconSize;
627d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        lp.height = mVolumeGroupListItemIconSize;
628d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        icon.setLayoutParams(lp);
629d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim    }
630d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim
631c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private void animateLayoutHeight(final View view, int targetHeight) {
632c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        final int startValue = getLayoutHeight(view);
633c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        final int endValue = targetHeight;
634c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        Animation anim = new Animation() {
635c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            @Override
636c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            protected void applyTransformation(float interpolatedTime, Transformation t) {
637c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                int height = startValue - (int) ((startValue - endValue) * interpolatedTime);
638c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                setLayoutHeight(view, height);
63904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            }
640c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        };
641c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        anim.setDuration(mGroupListAnimationDurationMs);
642c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        if (android.os.Build.VERSION.SDK_INT >= 21) {
643c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            anim.setInterpolator(mContext, mIsGroupExpanded ? R.interpolator.mr_linear_out_slow_in
644c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                    : R.interpolator.mr_fast_out_slow_in);
64504b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        }
646af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang        if (view == mVolumeGroupList) {
647af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang            anim.setAnimationListener(new Animation.AnimationListener() {
648af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                @Override
649af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                public void onAnimationStart(Animation animation) {
650af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                    mVolumeGroupList.setTranscriptMode(ListView.TRANSCRIPT_MODE_ALWAYS_SCROLL);
651af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                }
652af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang
653af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                @Override
654af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                public void onAnimationEnd(Animation animation) {
655af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                    mVolumeGroupList.setTranscriptMode(ListView.TRANSCRIPT_MODE_DISABLED);
656af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                }
657af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang
658af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                @Override
659af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang                public void onAnimationRepeat(Animation animation) { }
660af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang            });
661af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang        }
662c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        view.startAnimation(anim);
6632c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    }
6642c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
66570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private void updateVolumeControlLayout() {
6661ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        if (!mVolumeSliderTouched) {
6677447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            if (isVolumeControlAvailable(mRoute)) {
66870cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                mVolumeControlLayout.setVisibility(View.VISIBLE);
6691ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeSlider.setMax(mRoute.getVolumeMax());
6701ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeSlider.setProgress(mRoute.getVolume());
671050b7ec33bd9a2fe493f0b0b85d49ed213046219Jae Seo                if (getGroup() == null) {
672050b7ec33bd9a2fe493f0b0b85d49ed213046219Jae Seo                    mGroupExpandCollapseButton.setVisibility(View.GONE);
673050b7ec33bd9a2fe493f0b0b85d49ed213046219Jae Seo                } else {
674050b7ec33bd9a2fe493f0b0b85d49ed213046219Jae Seo                    mGroupExpandCollapseButton.setVisibility(View.VISIBLE);
675050b7ec33bd9a2fe493f0b0b85d49ed213046219Jae Seo                    VolumeGroupAdapter adapter =
676050b7ec33bd9a2fe493f0b0b85d49ed213046219Jae Seo                            (VolumeGroupAdapter) mVolumeGroupList.getAdapter();
677050b7ec33bd9a2fe493f0b0b85d49ed213046219Jae Seo                    if (adapter != null) {
678c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                       adapter.notifyDataSetChanged();
6791ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    }
6801ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
6811ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else {
68270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                mVolumeControlLayout.setVisibility(View.GONE);
6831ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
6842c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            updateLayoutHeight();
68570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        } else if (mVolumeControlLayout.getVisibility() == View.VISIBLE) {
6867447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            mVolumeSlider.setProgress(mRoute.getVolume());
6877447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            if (mIsGroupExpanded) {
6887447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
6898f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                    SeekBar volumeSlider = (SeekBar) mVolumeGroupList.getChildAt(i)
6908f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                            .findViewById(R.id.mr_volume_slider);
6918f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                    int tag = (int) volumeSlider.getTag();
6928f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                    int index = tag - VOLUME_SLIDER_TAG_GROUP_BASE;
6938f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                    if (index < 0 || index >= getGroup().getRouteCount()) {
6948f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                        continue;
6958f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                    }
6968f9ed131ec377643e2d10710187e262e4a4ad73aJaewan Kim                    MediaRouter.RouteInfo route = getGroup().getRouteAt(index);
6977447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    if (isVolumeControlAvailable(route)) {
6987447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                        volumeSlider.setProgress(route.getVolume());
6997447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    }
7007447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                }
7017447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            }
7021ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        }
7031ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    }
7041ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
70570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private void updatePlaybackControlLayout() {
70670cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        if (canShowPlaybackControlLayout()) {
7071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            CharSequence title = mDescription == null ? null : mDescription.getTitle();
7081ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            boolean hasTitle = !TextUtils.isEmpty(title);
7091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
7101ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle();
7111ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            boolean hasSubtitle = !TextUtils.isEmpty(subtitle);
7121ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
7138fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            boolean showTitle = false;
7148fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            boolean showSubtitle = false;
7158fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            if (mRoute.getPresentationDisplayId()
7168fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) {
7178fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                // The user is currently casting screen.
7188fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_casting_screen);
7198fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
7208fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            } else if (mState == null || mState.getState() == PlaybackStateCompat.STATE_NONE) {
7218fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_no_media_selected);
7228fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
7238fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            } else if (!hasTitle && !hasSubtitle) {
7248fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_no_info_available);
7258fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
7261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else {
7278fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                if (hasTitle) {
7288fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    mTitleView.setText(title);
7298fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    showTitle = true;
7308fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                }
7318fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                if (hasSubtitle) {
7328fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    mSubtitleView.setText(subtitle);
7338fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    showSubtitle = true;
7348fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                }
7351ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
7368fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            mTitleView.setVisibility(showTitle ? View.VISIBLE : View.GONE);
7378fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            mSubtitleView.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
7388fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang
7391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            if (mState != null) {
7401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
7411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
7421ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
7431ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
7441ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
7451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
7461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                if (isPlaying && supportsPause) {
7471ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setVisibility(View.VISIBLE);
7481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
7494c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                            mContext, R.attr.mediaRoutePauseDrawable));
7504c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                    mPlayPauseButton.setContentDescription(mContext.getResources()
7511ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            .getText(R.string.mr_controller_pause));
7521ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                } else if (!isPlaying && supportsPlay) {
7531ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setVisibility(View.VISIBLE);
7541ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
7554c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                            mContext, R.attr.mediaRoutePlayDrawable));
7564c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                    mPlayPauseButton.setContentDescription(mContext.getResources()
7571ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                            .getText(R.string.mr_controller_play));
7581ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                } else {
7591ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mPlayPauseButton.setVisibility(View.GONE);
7601ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
7611ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
7621ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        }
7632c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        updateLayoutHeight();
7642b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang    }
7652b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang
7667447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim    private boolean isVolumeControlAvailable(MediaRouter.RouteInfo route) {
7677447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim        return mVolumeControlEnabled && route.getVolumeHandling()
7687447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
769f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
770f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
77104b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    private static int getLayoutHeight(View view) {
77204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        return view.getLayoutParams().height;
77304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    }
77404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang
775be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang    private static void setLayoutHeight(View view, int height) {
776be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        ViewGroup.LayoutParams lp = view.getLayoutParams();
777be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        lp.height = height;
778be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        view.setLayoutParams(lp);
779be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang    }
780be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang
78104b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    private static int getLayoutBottomMargin(View view) {
78204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        return ((ViewGroup.MarginLayoutParams) view.getLayoutParams()).bottomMargin;
78304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    }
78404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang
78504b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    private static void setLayoutBottomMargin(View view, int bottomMargin) {
78604b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
78704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        params.bottomMargin = bottomMargin;
78804b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        view.setLayoutParams(params);
78904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    }
79004b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang
79113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    /**
79213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     * Returns desired art height to fit into controller dialog.
79313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     */
79413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    private int getDesiredArtHeight(int originalWidth, int originalHeight) {
79513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        if (originalWidth >= originalHeight) {
79613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            // For landscape art, fit width to dialog width.
797f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo            return (int) ((float) mDialogContentWidth * originalHeight / originalWidth + 0.5f);
79813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        }
79913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        // For portrait art, fit height to 16:9 ratio case's height.
800f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo        return (int) ((float) mDialogContentWidth * 9 / 16 + 0.5f);
80113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    }
80213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim
80311417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final class MediaRouterCallback extends MediaRouter.Callback {
80411417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
80511417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
80611417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
80711417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
80811417b1cfde8f1749905f2d735623af9214148afJeff Brown
80911417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
81011417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
81111417b1cfde8f1749905f2d735623af9214148afJeff Brown            update();
81211417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
81311417b1cfde8f1749905f2d735623af9214148afJeff Brown
81411417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
81511417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
81611417b1cfde8f1749905f2d735623af9214148afJeff Brown            if (route == mRoute) {
81770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                updateVolumeControlLayout();
81894be6100218126ce6a08bf1f56209578500b361fRoboErik            }
81994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
82094be6100218126ce6a08bf1f56209578500b361fRoboErik    }
82194be6100218126ce6a08bf1f56209578500b361fRoboErik
82294be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class MediaControllerCallback extends MediaControllerCompat.Callback {
82394be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
82494be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onSessionDestroyed() {
82594be6100218126ce6a08bf1f56209578500b361fRoboErik            if (mMediaController != null) {
82694be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController.unregisterCallback(mControllerCallback);
82794be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController = null;
82894be6100218126ce6a08bf1f56209578500b361fRoboErik            }
82994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
83094be6100218126ce6a08bf1f56209578500b361fRoboErik
83194be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
83294be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onPlaybackStateChanged(PlaybackStateCompat state) {
83394be6100218126ce6a08bf1f56209578500b361fRoboErik            mState = state;
83494be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
83594be6100218126ce6a08bf1f56209578500b361fRoboErik        }
83694be6100218126ce6a08bf1f56209578500b361fRoboErik
83794be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
83894be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onMetadataChanged(MediaMetadataCompat metadata) {
83994be6100218126ce6a08bf1f56209578500b361fRoboErik            mDescription = metadata == null ? null : metadata.getDescription();
84094be6100218126ce6a08bf1f56209578500b361fRoboErik            update();
84194be6100218126ce6a08bf1f56209578500b361fRoboErik        }
84294be6100218126ce6a08bf1f56209578500b361fRoboErik    }
84394be6100218126ce6a08bf1f56209578500b361fRoboErik
84494be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class ClickListener implements View.OnClickListener {
84594be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
84694be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onClick(View v) {
84794be6100218126ce6a08bf1f56209578500b361fRoboErik            int id = v.getId();
84806991009e52024cbb3dde550988e06149e77a269Jae Seo            if (id == BUTTON_STOP_RES_ID || id == BUTTON_DISCONNECT_RES_ID) {
84994be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mRoute.isSelected()) {
85006991009e52024cbb3dde550988e06149e77a269Jae Seo                    mRouter.unselect(id == BUTTON_STOP_RES_ID ?
85194be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_STOPPED :
85294be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_DISCONNECTED);
85394be6100218126ce6a08bf1f56209578500b361fRoboErik                }
85494be6100218126ce6a08bf1f56209578500b361fRoboErik                dismiss();
8557ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            } else if (id == R.id.mr_control_play_pause) {
85694be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mMediaController != null && mState != null) {
857ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_PLAYING;
858ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    if (isPlaying) {
85994be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().pause();
86094be6100218126ce6a08bf1f56209578500b361fRoboErik                    } else {
86194be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().play();
86294be6100218126ce6a08bf1f56209578500b361fRoboErik                    }
863ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    // Announce the action for accessibility.
864ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()) {
865ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                        AccessibilityEvent event = AccessibilityEvent.obtain(
866ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                                AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
8674c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                        event.setPackageName(mContext.getPackageName());
868ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                        event.setClassName(getClass().getName());
869ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                        int resId = isPlaying ?
870ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                                R.string.mr_controller_pause : R.string.mr_controller_play;
8714c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                        event.getText().add(mContext.getString(resId));
872ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                        mAccessibilityManager.sendAccessibilityEvent(event);
873ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    }
87494be6100218126ce6a08bf1f56209578500b361fRoboErik                }
8751ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else if (id == R.id.mr_close) {
876b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim                dismiss();
87711417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
87811417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
87911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
880005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
881435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private class VolumeChangeListener implements OnSeekBarChangeListener {
882435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        private final Runnable mStopTrackingTouch = new Runnable() {
8836051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            @Override
884435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            public void run() {
885435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                if (mVolumeSliderTouched) {
886435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                    mVolumeSliderTouched = false;
88770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                    updateVolumeControlLayout();
8886051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                }
8896051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
890435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        };
8916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
892435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
893435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onStartTrackingTouch(SeekBar seekBar) {
894435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            if (mVolumeSliderTouched) {
895435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                mVolumeSlider.removeCallbacks(mStopTrackingTouch);
896435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            } else {
897435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                mVolumeSliderTouched = true;
8986051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
899435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
9006051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
901435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
902435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onStopTrackingTouch(SeekBar seekBar) {
903435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // Defer resetting mVolumeSliderTouched to allow the media route provider
904435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // a little time to settle into its new state and publish the final
905435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // volume update.
906435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
907435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
908435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim
909435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
910435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
911435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            if (fromUser) {
912435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                int tag = (int) seekBar.getTag();
913435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                if (tag == VOLUME_SLIDER_TAG_MASTER) {
914435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                    mRoute.requestSetVolume(progress);
915d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                } else {
916d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                    int index = tag - VOLUME_SLIDER_TAG_GROUP_BASE;
917d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                    if (index >= 0 && index < getGroup().getRouteCount()) {
918d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                        getGroup().getRouteAt(index).requestSetVolume(progress);
919d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                    }
920435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                }
9216051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
922435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
923435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    }
924435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim
925435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> {
926d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo        final float mDisabledAlpha;
9276051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
9286051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) {
9296051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            super(context, 0, objects);
930d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo            mDisabledAlpha = MediaRouterThemeHelper.getDisabledAlpha(context);
9316051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
9326051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
9336051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        @Override
9346051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public View getView(final int position, View convertView, ViewGroup parent) {
9356051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            View v = convertView;
9366051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (v == null) {
9374c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                v = LayoutInflater.from(mContext).inflate(
9382c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                        R.layout.mr_controller_volume_item, parent, false);
939d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim            } else {
940d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim                updateVolumeGroupItemHeight(v);
9416051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
94219d268075834665bf62567b224dcd3549c92d3c3Jae Seo
9436051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            MediaRouter.RouteInfo route = getItem(position);
9446051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (route != null) {
9450e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                boolean isEnabled = route.isEnabled();
9460e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
9477ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                TextView routeName = (TextView) v.findViewById(R.id.mr_name);
9480e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setEnabled(isEnabled);
9490e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setText(route.getName());
9506051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
951ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                MediaRouteVolumeSlider volumeSlider =
952ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                        (MediaRouteVolumeSlider) v.findViewById(R.id.mr_volume_slider);
953d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                MediaRouterThemeHelper.setVolumeSliderColor(
954d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                        mContext, volumeSlider, mVolumeGroupList);
955d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                volumeSlider.setTag(VOLUME_SLIDER_TAG_GROUP_BASE + position);
9560b72510d7bc402b71065e069852d10a8592d55deJaewan Kim                volumeSlider.setHideThumb(!isEnabled);
957d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                volumeSlider.setEnabled(isEnabled);
9580e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                if (isEnabled) {
9597447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    if (isVolumeControlAvailable(route)) {
9600e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(route.getVolumeMax());
9610e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(route.getVolume());
962435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                        volumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
9630e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    } else {
9640e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(100);
9650e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(100);
9660e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setEnabled(false);
9670e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    }
9680e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                }
9690e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
9700e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                ImageView volumeItemIcon =
9717ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        (ImageView) v.findViewById(R.id.mr_volume_item_icon);
972d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                volumeItemIcon.setAlpha(isEnabled ? 0xFF : (int) (0xFF * mDisabledAlpha));
9736051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
9746051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return v;
9756051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
9766051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
9776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
978005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> {
9798bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        final Bitmap mIconBitmap;
9808bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        final Uri mIconUri;
9818bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        int mBackgroundColor;
9828bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
9838bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        FetchArtTask() {
9848bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            mIconBitmap = mDescription == null ? null : mDescription.getIconBitmap();
9858bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            mIconUri = mDescription == null ? null : mDescription.getIconUri();
9868bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        }
9878bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
9888bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        @Override
9898bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        protected void onPreExecute() {
9908bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            if (mArtIconBitmap == mIconBitmap && mArtIconUri == mIconUri) {
9918bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                // Already handled the current art.
9928bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                cancel(true);
9938bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            }
9948bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        }
995005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
996005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
997005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        protected Bitmap doInBackground(Void... arg) {
99813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            Bitmap art = null;
9998bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            if (mIconBitmap != null) {
10008bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                art = mIconBitmap;
10018bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            } else if (mIconUri != null) {
10028bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                String scheme = mIconUri.getScheme();
1003005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                if (!(ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
1004005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        || ContentResolver.SCHEME_CONTENT.equals(scheme)
1005005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        || ContentResolver.SCHEME_FILE.equals(scheme))) {
1006005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    Log.w(TAG, "Icon Uri should point to local resources.");
1007005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    return null;
1008005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                }
1009005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                BufferedInputStream stream = null;
1010005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                try {
1011005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    stream = new BufferedInputStream(
10124c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                            mContext.getContentResolver().openInputStream(mIconUri));
1013005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
101413d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Query art size.
1015005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.Options options = new BitmapFactory.Options();
1016005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = true;
1017005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.decodeStream(stream, null, options);
101813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    if (options.outWidth == 0 || options.outHeight == 0) {
101913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                        return null;
102013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    }
102113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Rewind the stream in order to restart art decoding.
1022005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    try {
1023005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.reset();
1024005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    } catch (IOException e) {
1025005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        // Failed to rewind the stream, try to reopen it.
1026005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.close();
10274c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                        stream = new BufferedInputStream(mContext.getContentResolver()
10288bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                                .openInputStream(mIconUri));
1029005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
103013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Calculate required size to decode the art and possibly resize it.
1031005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = false;
103213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight);
103313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int ratio = options.outHeight / reqHeight;
1034005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio));
1035005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (isCancelled()) {
1036005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        return null;
1037005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
103813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    art = BitmapFactory.decodeStream(stream, null, options);
1039005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } catch (IOException e){
10408bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                    Log.w(TAG, "Unable to open: " + mIconUri, e);
1041005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } finally {
1042005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (stream != null) {
1043005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        try {
1044005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                            stream.close();
1045005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        } catch (IOException e) {
1046005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        }
1047005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
1048005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                }
1049005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
1050145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim            if (art != null && art.getWidth() < art.getHeight()) {
1051c4c371f91673a882177f16fa95723e7e69f54882Insun Kang                // Portrait art requires dominant color as background color.
1052145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                Palette palette = new Palette.Builder(art).maximumColorCount(1).generate();
1053be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang                mBackgroundColor = palette.getSwatches().isEmpty()
1054145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                        ? 0 : palette.getSwatches().get(0).getRgb();
1055005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
105613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            return art;
1057005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
1058005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
1059005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
1060005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        protected void onCancelled() {
1061005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = null;
1062005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
1063005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
1064005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
106513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        protected void onPostExecute(Bitmap art) {
1066005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = null;
10678bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            if (mArtIconBitmap != mIconBitmap || mArtIconUri != mIconUri) {
10688bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtIconBitmap = mIconBitmap;
10698bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtIconUri = mIconUri;
10708bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
10718bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtView.setImageBitmap(art);
10728bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtView.setBackgroundColor(mBackgroundColor);
10732c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                updateLayoutHeight();
10748bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            }
1075005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
1076005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    }
10776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo}
1078