111417b1cfde8f1749905f2d735623af9214148afJeff Brown/*
2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 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
17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.mediarouter.app;
1811417b1cfde8f1749905f2d735623af9214148afJeff Brown
196a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Choimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_PAUSE;
206a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Choimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY;
216a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Choimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY_PAUSE;
226a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Choimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_STOP;
236a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho
24f291fbba316ca92573d84dbe37e48e9d83181318Jae Seoimport android.app.PendingIntent;
25005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.content.ContentResolver;
2611417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.content.Context;
27c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kimimport android.content.res.Resources;
28005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.Bitmap;
29005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.graphics.BitmapFactory;
302c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kimimport android.graphics.Rect;
3113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kimimport android.graphics.drawable.BitmapDrawable;
32005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.net.Uri;
33005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport android.os.AsyncTask;
3411417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.os.Bundle;
3594be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.os.RemoteException;
3687654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Choimport android.os.SystemClock;
3794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaDescriptionCompat;
3894be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.MediaMetadataCompat;
3994be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.MediaSessionCompat;
4094be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.support.v4.media.session.PlaybackStateCompat;
4194be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.text.TextUtils;
4294be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.util.Log;
4311417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.KeyEvent;
446051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.LayoutInflater;
4511417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.view.View;
4640dd800ece983a94ea6a26a27481da50f489e7c8Jaewan Kimimport android.view.View.MeasureSpec;
476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.view.ViewGroup;
4886dcb627078ea297c4337ed634fc3fe874e23897Jae Seoimport android.view.ViewTreeObserver;
49ee7ae661b02471fe598566b1e90adbacda240b0bJae Seoimport android.view.accessibility.AccessibilityEvent;
50ee7ae661b02471fe598566b1e90adbacda240b0bJae Seoimport android.view.accessibility.AccessibilityManager;
511c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport android.view.animation.AccelerateDecelerateInterpolator;
521c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport android.view.animation.AlphaAnimation;
5304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kangimport android.view.animation.Animation;
541c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport android.view.animation.AnimationSet;
551c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport android.view.animation.AnimationUtils;
561c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport android.view.animation.Interpolator;
5704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kangimport android.view.animation.Transformation;
581c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport android.view.animation.TranslateAnimation;
596051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport android.widget.ArrayAdapter;
6011417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.Button;
6111417b1cfde8f1749905f2d735623af9214148afJeff Brownimport android.widget.FrameLayout;
6294be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageButton;
6394be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.ImageView;
64f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.LinearLayout;
657ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Limimport android.widget.RelativeLayout;
66f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shahimport android.widget.SeekBar;
6794be6100218126ce6a08bf1f56209578500b361fRoboErikimport android.widget.TextView;
68ee1b969af871a7015fc2df11f8d342a4e6cf40f0Hyundo Moon
69f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikasimport androidx.appcompat.app.AlertDialog;
70f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikasimport androidx.core.util.ObjectsCompat;
71f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikasimport androidx.core.view.accessibility.AccessibilityEventCompat;
7224919ee8c30d91ec056cae6c4f578d7007cbe968Aurimas Liutikasimport android.support.v4.media.session.MediaControllerCompat;
73f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikasimport androidx.mediarouter.R;
74f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikasimport androidx.mediarouter.media.MediaRouteSelector;
75f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikasimport androidx.mediarouter.media.MediaRouter;
76f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikasimport androidx.palette.graphics.Palette;
77f2d1695bf23114f2a5d6bfc9e092a4bfcb5b2701Aurimas Liutikas
78005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.BufferedInputStream;
79005482649154d0970693b3967241eb4d2cb22003Jaewan Kimimport java.io.IOException;
801c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport java.io.InputStream;
81376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Choimport java.net.URL;
82376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Choimport java.net.URLConnection;
831c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport java.util.ArrayList;
84dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Limimport java.util.HashMap;
851c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport java.util.HashSet;
866051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seoimport java.util.List;
87dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Limimport java.util.Map;
881c4fce94062e162e579d20134f0bac767bdf0964Donghyun Choimport java.util.Set;
89376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Choimport java.util.concurrent.TimeUnit;
90005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
9111417b1cfde8f1749905f2d735623af9214148afJeff Brown/**
9211417b1cfde8f1749905f2d735623af9214148afJeff Brown * This class implements the route controller dialog for {@link MediaRouter}.
9311417b1cfde8f1749905f2d735623af9214148afJeff Brown * <p>
9411417b1cfde8f1749905f2d735623af9214148afJeff Brown * This dialog allows the user to control or disconnect from the currently selected route.
9511417b1cfde8f1749905f2d735623af9214148afJeff Brown * </p>
9611417b1cfde8f1749905f2d735623af9214148afJeff Brown *
9711417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteButton
9811417b1cfde8f1749905f2d735623af9214148afJeff Brown * @see MediaRouteActionProvider
9911417b1cfde8f1749905f2d735623af9214148afJeff Brown */
10089530d511efd566d53bedd9178454dd01d227c61Jae Seopublic class MediaRouteControllerDialog extends AlertDialog {
101ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang    // Tags should be less than 24 characters long (see docs for android.util.Log.isLoggable())
102e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    static final String TAG = "MediaRouteCtrlDialog";
103e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
10411417b1cfde8f1749905f2d735623af9214148afJeff Brown
105f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // Time to wait before updating the volume when the user lets go of the seek bar
106f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // to allow the route provider time to propagate the change and publish a new
107f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    // route descriptor.
108e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    static final int VOLUME_UPDATE_DELAY_MILLIS = 500;
109e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    static final int CONNECTION_TIMEOUT_MILLIS = (int) TimeUnit.SECONDS.toMillis(30L);
110f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
11106991009e52024cbb3dde550988e06149e77a269Jae Seo    private static final int BUTTON_NEUTRAL_RES_ID = android.R.id.button3;
112e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    static final int BUTTON_DISCONNECT_RES_ID = android.R.id.button2;
113e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    static final int BUTTON_STOP_RES_ID = android.R.id.button1;
11406991009e52024cbb3dde550988e06149e77a269Jae Seo
115e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    final MediaRouter mRouter;
11611417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final MediaRouterCallback mCallback;
117e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    final MediaRouter.RouteInfo mRoute;
11811417b1cfde8f1749905f2d735623af9214148afJeff Brown
119e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Context mContext;
120eff7719415542ba819054863b0995f07742a7a8aJeff Brown    private boolean mCreated;
121e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private boolean mAttachedToWindow;
122e2148398ae5d03c22789aebc3d6359b5ff86c077Jae Seo
123f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo    private int mDialogContentWidth;
12411417b1cfde8f1749905f2d735623af9214148afJeff Brown
1257ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private View mCustomControlView;
12611417b1cfde8f1749905f2d735623af9214148afJeff Brown
12711417b1cfde8f1749905f2d735623af9214148afJeff Brown    private Button mDisconnectButton;
12894be6100218126ce6a08bf1f56209578500b361fRoboErik    private Button mStopCastingButton;
1296a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho    private ImageButton mPlaybackControlButton;
130b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim    private ImageButton mCloseButton;
131328f1006c17ddeb3eb563580bcd6638e1cfb4320Jaewan Kim    private MediaRouteExpandCollapseButton mGroupExpandCollapseButton;
13294be6100218126ce6a08bf1f56209578500b361fRoboErik
133c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private FrameLayout mExpandableAreaLayout;
134c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private LinearLayout mDialogAreaLayout;
135e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    FrameLayout mDefaultControlLayout;
136c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private FrameLayout mCustomControlLayout;
13794be6100218126ce6a08bf1f56209578500b361fRoboErik    private ImageView mArtView;
1381ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private TextView mTitleView;
1391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private TextView mSubtitleView;
1407ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim    private TextView mRouteNameTextView;
14194be6100218126ce6a08bf1f56209578500b361fRoboErik
142f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    private boolean mVolumeControlEnabled = true;
14304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    // Layout for media controllers including play/pause button and the main volume slider.
1442c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    private LinearLayout mMediaMainControlLayout;
14570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private RelativeLayout mPlaybackControlLayout;
14670cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private LinearLayout mVolumeControlLayout;
1471ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    private View mDividerView;
1481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
149e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    OverlayListView mVolumeGroupList;
150e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    VolumeGroupAdapter mVolumeGroupAdapter;
1512242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho    private List<MediaRouter.RouteInfo> mGroupMemberRoutes;
152e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Set<MediaRouter.RouteInfo> mGroupMemberRoutesAdded;
1531c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private Set<MediaRouter.RouteInfo> mGroupMemberRoutesRemoved;
154e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Set<MediaRouter.RouteInfo> mGroupMemberRoutesAnimatingWithBitmap;
155e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    SeekBar mVolumeSlider;
156e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    VolumeChangeListener mVolumeChangeListener;
157e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    MediaRouter.RouteInfo mRouteInVolumeSliderTouched;
158c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListItemIconSize;
159c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListItemHeight;
160c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private int mVolumeGroupListMaxHeight;
161c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim    private final int mVolumeGroupListPaddingTop;
162e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Map<MediaRouter.RouteInfo, SeekBar> mVolumeSliderMap;
163e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
164e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    MediaControllerCompat mMediaController;
165e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    MediaControllerCallback mControllerCallback;
166e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    PlaybackStateCompat mState;
167e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    MediaDescriptionCompat mDescription;
168e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
169e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    FetchArtTask mFetchArtTask;
170e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Bitmap mArtIconBitmap;
171e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Uri mArtIconUri;
172e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    boolean mArtIconIsLoaded;
173e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Bitmap mArtIconLoadedBitmap;
174e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    int mArtIconBackgroundColor;
175e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
176e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    boolean mHasPendingUpdate;
177e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    boolean mPendingUpdateAnimationNeeded;
178e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
179e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    boolean mIsGroupExpanded;
180e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    boolean mIsGroupListAnimating;
181e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    boolean mIsGroupListAnimationPending;
182e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    int mGroupListAnimationDurationMs;
1831c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private int mGroupListFadeInDurationMs;
1841c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private int mGroupListFadeOutDurationMs;
1851c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
1861c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private Interpolator mInterpolator;
1871c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private Interpolator mLinearOutSlowInInterpolator;
1881c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private Interpolator mFastOutSlowInInterpolator;
1891c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private Interpolator mAccelerateDecelerateInterpolator;
19011417b1cfde8f1749905f2d735623af9214148afJeff Brown
191e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    final AccessibilityManager mAccessibilityManager;
192ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo
193e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    Runnable mGroupListFadeInAnimation = new Runnable() {
1941c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        @Override
1951c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        public void run() {
1961c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            startGroupListFadeInAnimation();
1971c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
1981c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    };
1991c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
20011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context) {
20111417b1cfde8f1749905f2d735623af9214148afJeff Brown        this(context, 0);
20211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
20311417b1cfde8f1749905f2d735623af9214148afJeff Brown
20411417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouteControllerDialog(Context context, int theme) {
2050fa3ac22663f0eecb24e7e68d6c4992e6fd32c19Christofer Ã…kersten        super(context = MediaRouterThemeHelper.createThemedDialogContext(context, theme, true),
2060fa3ac22663f0eecb24e7e68d6c4992e6fd32c19Christofer Ã…kersten                MediaRouterThemeHelper.createThemedDialogStyle(context));
2074c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        mContext = getContext();
20811417b1cfde8f1749905f2d735623af9214148afJeff Brown
20994be6100218126ce6a08bf1f56209578500b361fRoboErik        mControllerCallback = new MediaControllerCallback();
2104448a8e5ed20d230cb838042ff73b6409106cf80Sungsoo Lim        mRouter = MediaRouter.getInstance(mContext);
21111417b1cfde8f1749905f2d735623af9214148afJeff Brown        mCallback = new MediaRouterCallback();
21211417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRoute = mRouter.getSelectedRoute();
213e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
2144448a8e5ed20d230cb838042ff73b6409106cf80Sungsoo Lim        mVolumeGroupListPaddingTop = mContext.getResources().getDimensionPixelSize(
215c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_padding_top);
216ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo        mAccessibilityManager =
2174448a8e5ed20d230cb838042ff73b6409106cf80Sungsoo Lim                (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
2181c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (android.os.Build.VERSION.SDK_INT >= 21) {
2191c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
2201c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    R.interpolator.mr_linear_out_slow_in);
2211c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
2221c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    R.interpolator.mr_fast_out_slow_in);
2231c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
2241c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mAccelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
22511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
22611417b1cfde8f1749905f2d735623af9214148afJeff Brown
22711417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
22811417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the route that this dialog is controlling.
22911417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
23011417b1cfde8f1749905f2d735623af9214148afJeff Brown    public MediaRouter.RouteInfo getRoute() {
23111417b1cfde8f1749905f2d735623af9214148afJeff Brown        return mRoute;
23211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
23311417b1cfde8f1749905f2d735623af9214148afJeff Brown
2346051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    private MediaRouter.RouteGroup getGroup() {
2356051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        if (mRoute instanceof MediaRouter.RouteGroup) {
2366051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return (MediaRouter.RouteGroup) mRoute;
2376051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
2386051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        return null;
2396051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
2406051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
24111417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
24256d9fd2c2746f50e6a31e24b19e8671bba31a842Dongwon Kang     * Provides the subclass an opportunity to create a view that will replace the default media
24356d9fd2c2746f50e6a31e24b19e8671bba31a842Dongwon Kang     * controls for the currently playing content.
24411417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
24511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @param savedInstanceState The dialog's saved instance state.
24611417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
24711417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
24811417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View onCreateMediaControlView(Bundle savedInstanceState) {
24911417b1cfde8f1749905f2d735623af9214148afJeff Brown        return null;
25011417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
25111417b1cfde8f1749905f2d735623af9214148afJeff Brown
25211417b1cfde8f1749905f2d735623af9214148afJeff Brown    /**
25311417b1cfde8f1749905f2d735623af9214148afJeff Brown     * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}.
25411417b1cfde8f1749905f2d735623af9214148afJeff Brown     *
25511417b1cfde8f1749905f2d735623af9214148afJeff Brown     * @return The media control view, or null if none.
25611417b1cfde8f1749905f2d735623af9214148afJeff Brown     */
25711417b1cfde8f1749905f2d735623af9214148afJeff Brown    public View getMediaControlView() {
2587ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        return mCustomControlView;
25911417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
26011417b1cfde8f1749905f2d735623af9214148afJeff Brown
261eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
262f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Sets whether to enable the volume slider and volume control using the volume keys
263f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
264f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * <p>
265f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * The default value is true.
266f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * </p>
267f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
268f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public void setVolumeControlEnabled(boolean enable) {
269f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        if (mVolumeControlEnabled != enable) {
270f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            mVolumeControlEnabled = enable;
271f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            if (mCreated) {
27275322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho                update(false);
273f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah            }
274f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        }
275f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
276f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
277f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
278f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * Returns whether to enable the volume slider and volume control using the volume keys
279f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     * when the route supports it.
280f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah     */
281f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    public boolean isVolumeControlEnabled() {
282f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah        return mVolumeControlEnabled;
283f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
284f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
285f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    /**
28694be6100218126ce6a08bf1f56209578500b361fRoboErik     * Set the session to use for metadata and transport controls. The dialog
28794be6100218126ce6a08bf1f56209578500b361fRoboErik     * will listen to changes on this session and update the UI automatically in
28894be6100218126ce6a08bf1f56209578500b361fRoboErik     * response to changes.
28994be6100218126ce6a08bf1f56209578500b361fRoboErik     *
29094be6100218126ce6a08bf1f56209578500b361fRoboErik     * @param sessionToken The token for the session to use.
291eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
292e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik    private void setMediaSession(MediaSessionCompat.Token sessionToken) {
29394be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
29494be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.unregisterCallback(mControllerCallback);
29594be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController = null;
29694be6100218126ce6a08bf1f56209578500b361fRoboErik        }
29794be6100218126ce6a08bf1f56209578500b361fRoboErik        if (sessionToken == null) {
29894be6100218126ce6a08bf1f56209578500b361fRoboErik            return;
29994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
300e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        if (!mAttachedToWindow) {
301e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik            return;
302e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        }
30394be6100218126ce6a08bf1f56209578500b361fRoboErik        try {
3044c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang            mMediaController = new MediaControllerCompat(mContext, sessionToken);
30594be6100218126ce6a08bf1f56209578500b361fRoboErik        } catch (RemoteException e) {
30694be6100218126ce6a08bf1f56209578500b361fRoboErik            Log.e(TAG, "Error creating media controller in setMediaSession.", e);
30794be6100218126ce6a08bf1f56209578500b361fRoboErik        }
30894be6100218126ce6a08bf1f56209578500b361fRoboErik        if (mMediaController != null) {
30994be6100218126ce6a08bf1f56209578500b361fRoboErik            mMediaController.registerCallback(mControllerCallback);
310eff7719415542ba819054863b0995f07742a7a8aJeff Brown        }
31194be6100218126ce6a08bf1f56209578500b361fRoboErik        MediaMetadataCompat metadata = mMediaController == null ? null
31294be6100218126ce6a08bf1f56209578500b361fRoboErik                : mMediaController.getMetadata();
31394be6100218126ce6a08bf1f56209578500b361fRoboErik        mDescription = metadata == null ? null : metadata.getDescription();
31494be6100218126ce6a08bf1f56209578500b361fRoboErik        mState = mMediaController == null ? null : mMediaController.getPlaybackState();
31575322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        updateArtIconIfNeeded();
3161c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        update(false);
317eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
318eff7719415542ba819054863b0995f07742a7a8aJeff Brown
319eff7719415542ba819054863b0995f07742a7a8aJeff Brown    /**
32075dbda46b4ca20861e9d382b1662b3c34d20da8aInsun Kang     * Gets the session to use for metadata and transport controls.
32194be6100218126ce6a08bf1f56209578500b361fRoboErik     *
32275dbda46b4ca20861e9d382b1662b3c34d20da8aInsun Kang     * @return The token for the session to use or null if none.
323eff7719415542ba819054863b0995f07742a7a8aJeff Brown     */
32494be6100218126ce6a08bf1f56209578500b361fRoboErik    public MediaSessionCompat.Token getMediaSession() {
32594be6100218126ce6a08bf1f56209578500b361fRoboErik        return mMediaController == null ? null : mMediaController.getSessionToken();
326eff7719415542ba819054863b0995f07742a7a8aJeff Brown    }
327eff7719415542ba819054863b0995f07742a7a8aJeff Brown
32811417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
32911417b1cfde8f1749905f2d735623af9214148afJeff Brown    protected void onCreate(Bundle savedInstanceState) {
33011417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onCreate(savedInstanceState);
33111417b1cfde8f1749905f2d735623af9214148afJeff Brown
332c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        getWindow().setBackgroundDrawableResource(android.R.color.transparent);
333a09c7b30d3a5c53281db955eabce171e1aec6feaSungsoo Lim        setContentView(R.layout.mr_controller_material_dialog_b);
334f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo
33506991009e52024cbb3dde550988e06149e77a269Jae Seo        // Remove the neutral button.
33606991009e52024cbb3dde550988e06149e77a269Jae Seo        findViewById(BUTTON_NEUTRAL_RES_ID).setVisibility(View.GONE);
33706991009e52024cbb3dde550988e06149e77a269Jae Seo
33894be6100218126ce6a08bf1f56209578500b361fRoboErik        ClickListener listener = new ClickListener();
339d6748a7926ebb2450337f9f0ff4d445c980344e5Jeff Brown
340fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mExpandableAreaLayout = findViewById(R.id.mr_expandable_area);
341c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mExpandableAreaLayout.setOnClickListener(new View.OnClickListener() {
342c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            @Override
343c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            public void onClick(View v) {
344c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                dismiss();
345c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            }
346c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        });
347fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mDialogAreaLayout = findViewById(R.id.mr_dialog_area);
348c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mDialogAreaLayout.setOnClickListener(new View.OnClickListener() {
349c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            @Override
350c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            public void onClick(View v) {
351c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                // Eat unhandled touch events.
352c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            }
353c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        });
3546f6fdaf79cd74810b2b96514c6914ae1dbe6c5f0Jae Seo        int color = MediaRouterThemeHelper.getButtonTextColor(mContext);
355fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mDisconnectButton = findViewById(BUTTON_DISCONNECT_RES_ID);
35606991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton.setText(R.string.mr_controller_disconnect);
3576f6fdaf79cd74810b2b96514c6914ae1dbe6c5f0Jae Seo        mDisconnectButton.setTextColor(color);
35894be6100218126ce6a08bf1f56209578500b361fRoboErik        mDisconnectButton.setOnClickListener(listener);
35911417b1cfde8f1749905f2d735623af9214148afJeff Brown
360fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mStopCastingButton = findViewById(BUTTON_STOP_RES_ID);
3616a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho        mStopCastingButton.setText(R.string.mr_controller_stop_casting);
3626f6fdaf79cd74810b2b96514c6914ae1dbe6c5f0Jae Seo        mStopCastingButton.setTextColor(color);
36394be6100218126ce6a08bf1f56209578500b361fRoboErik        mStopCastingButton.setOnClickListener(listener);
36411417b1cfde8f1749905f2d735623af9214148afJeff Brown
365fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mRouteNameTextView = findViewById(R.id.mr_name);
366fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mCloseButton = findViewById(R.id.mr_close);
367b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim        mCloseButton.setOnClickListener(listener);
368fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mCustomControlLayout = findViewById(R.id.mr_custom_control);
369fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mDefaultControlLayout = findViewById(R.id.mr_default_control);
370f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo
371f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        // Start the session activity when a content item (album art, title or subtitle) is clicked.
372f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        View.OnClickListener onClickListener = new View.OnClickListener() {
373f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo            @Override
374f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo            public void onClick(View v) {
375f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                if (mMediaController != null) {
376f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                    PendingIntent pi = mMediaController.getSessionActivity();
377f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                    if (pi != null) {
378f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                        try {
379f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                            pi.send();
380242b255caba1d6fdd651e32fffa68e0dbeb9b65bDongwon Kang                            dismiss();
381f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                        } catch (PendingIntent.CanceledException e) {
382f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                            Log.e(TAG, pi + " was not sent, it had been canceled.");
383f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                        }
384f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                    }
385f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo                }
386f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo            }
387f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        };
388fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mArtView = findViewById(R.id.mr_art);
389f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        mArtView.setOnClickListener(onClickListener);
390f291fbba316ca92573d84dbe37e48e9d83181318Jae Seo        findViewById(R.id.mr_control_title_container).setOnClickListener(onClickListener);
3916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
392fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mMediaMainControlLayout = findViewById(R.id.mr_media_main_control);
3931ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mDividerView = findViewById(R.id.mr_control_divider);
3941ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
395fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mPlaybackControlLayout = findViewById(R.id.mr_playback_control);
396fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mTitleView = findViewById(R.id.mr_control_title);
397fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mSubtitleView = findViewById(R.id.mr_control_subtitle);
398fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mPlaybackControlButton = findViewById(R.id.mr_control_playback_ctrl);
3996a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho        mPlaybackControlButton.setOnClickListener(listener);
4001ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
401fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mVolumeControlLayout = findViewById(R.id.mr_volume_control);
402dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim        mVolumeControlLayout.setVisibility(View.GONE);
403fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mVolumeSlider = findViewById(R.id.mr_volume_slider);
404dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim        mVolumeSlider.setTag(mRoute);
405435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeChangeListener = new VolumeChangeListener();
406435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        mVolumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
4071ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
408fa2e2acf79d791a90410025daad438968550d18cAlan Viverette        mVolumeGroupList = findViewById(R.id.mr_volume_group_list);
4092242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho        mGroupMemberRoutes = new ArrayList<MediaRouter.RouteInfo>();
410166da1fa21cc24216730da32c9b81c591349db87Donghyun Cho        mVolumeGroupAdapter = new VolumeGroupAdapter(mVolumeGroupList.getContext(),
411166da1fa21cc24216730da32c9b81c591349db87Donghyun Cho                mGroupMemberRoutes);
4122242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho        mVolumeGroupList.setAdapter(mVolumeGroupAdapter);
4131c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mGroupMemberRoutesAnimatingWithBitmap = new HashSet<>();
4142242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho
415d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo        MediaRouterThemeHelper.setMediaControlsBackgroundColor(mContext,
416d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                mMediaMainControlLayout, mVolumeGroupList, getGroup() != null);
417d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo        MediaRouterThemeHelper.setVolumeSliderColor(mContext,
418d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                (MediaRouteVolumeSlider) mVolumeSlider, mMediaMainControlLayout);
419dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim        mVolumeSliderMap = new HashMap<>();
420dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim        mVolumeSliderMap.put(mRoute, mVolumeSlider);
421d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo
422328f1006c17ddeb3eb563580bcd6638e1cfb4320Jaewan Kim        mGroupExpandCollapseButton =
423fa2e2acf79d791a90410025daad438968550d18cAlan Viverette                findViewById(R.id.mr_group_expand_collapse);
4241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() {
4251ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            @Override
4261ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            public void onClick(View v) {
4272b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang                mIsGroupExpanded = !mIsGroupExpanded;
4282b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang                if (mIsGroupExpanded) {
4291ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                    mVolumeGroupList.setVisibility(View.VISIBLE);
4301ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
4311c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                loadInterpolator();
4321c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                updateLayoutHeight(true);
4331ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
4341ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        });
4351c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        loadInterpolator();
4364c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        mGroupListAnimationDurationMs = mContext.getResources().getInteger(
437c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                R.integer.mr_controller_volume_group_list_animation_duration_ms);
4381c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mGroupListFadeInDurationMs = mContext.getResources().getInteger(
4391c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                R.integer.mr_controller_volume_group_list_fade_in_duration_ms);
4401c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mGroupListFadeOutDurationMs = mContext.getResources().getInteger(
4411c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                R.integer.mr_controller_volume_group_list_fade_out_duration_ms);
44211417b1cfde8f1749905f2d735623af9214148afJeff Brown
4437ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mCustomControlView = onCreateMediaControlView(savedInstanceState);
4447ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        if (mCustomControlView != null) {
4451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            mCustomControlLayout.addView(mCustomControlView);
4461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            mCustomControlLayout.setVisibility(View.VISIBLE);
44711417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
44886a802c8d09983d8725cccf59217e65d3e0c6373Jae Seo        mCreated = true;
449d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        updateLayout();
450d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    }
451d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
452d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    /**
453d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo     * Sets the width of the dialog. Also called when configuration changes.
454d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo     */
455d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo    void updateLayout() {
4564c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        int width = MediaRouteDialogHelper.getDialogWidth(mContext);
457d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        getWindow().setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT);
458d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
459d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        View decorView = getWindow().getDecorView();
460d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo        mDialogContentWidth = width - decorView.getPaddingLeft() - decorView.getPaddingRight();
461d52e30f3736a821e45266c28c334756f5f7e55c3Jae Seo
4624c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang        Resources res = mContext.getResources();
463c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListItemIconSize = res.getDimensionPixelSize(
464c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_item_icon_size);
465c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListItemHeight = res.getDimensionPixelSize(
466c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_item_height);
467c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        mVolumeGroupListMaxHeight = res.getDimensionPixelSize(
468c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim                R.dimen.mr_controller_volume_group_list_max_height);
469c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim
47075322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        // Fetch art icons again for layout changes to resize it accordingly
471c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        mArtIconBitmap = null;
472c74ed2dfd8328da1f1786f1e4fb07f0e8eebd35bJae Seo        mArtIconUri = null;
47375322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        updateArtIconIfNeeded();
4741c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        update(false);
47511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
47611417b1cfde8f1749905f2d735623af9214148afJeff Brown
47711417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
47811417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onAttachedToWindow() {
47911417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onAttachedToWindow();
480e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = true;
48111417b1cfde8f1749905f2d735623af9214148afJeff Brown
48211417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback,
48311417b1cfde8f1749905f2d735623af9214148afJeff Brown                MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
484e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(mRouter.getMediaSessionToken());
48511417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
48611417b1cfde8f1749905f2d735623af9214148afJeff Brown
48711417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
48811417b1cfde8f1749905f2d735623af9214148afJeff Brown    public void onDetachedFromWindow() {
48911417b1cfde8f1749905f2d735623af9214148afJeff Brown        mRouter.removeCallback(mCallback);
490e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        setMediaSession(null);
491e49860b0f76d8336c1d41831ed370b0ff94278efRoboErik        mAttachedToWindow = false;
49211417b1cfde8f1749905f2d735623af9214148afJeff Brown        super.onDetachedFromWindow();
49311417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
49411417b1cfde8f1749905f2d735623af9214148afJeff Brown
49511417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
49611417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyDown(int keyCode, KeyEvent event) {
497ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
498ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
499ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1);
500ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
50111417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
50211417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyDown(keyCode, event);
50311417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
50411417b1cfde8f1749905f2d735623af9214148afJeff Brown
50511417b1cfde8f1749905f2d735623af9214148afJeff Brown    @Override
50611417b1cfde8f1749905f2d735623af9214148afJeff Brown    public boolean onKeyUp(int keyCode, KeyEvent event) {
507ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
508ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
509ce8cbd614a64f94e54b936d66ecd14b6c1282ddfJeff Brown            return true;
51011417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
51111417b1cfde8f1749905f2d735623af9214148afJeff Brown        return super.onKeyUp(keyCode, event);
51211417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
51311417b1cfde8f1749905f2d735623af9214148afJeff Brown
514e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void update(boolean animate) {
515d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        // Defer dialog updates if a user is adjusting a volume in the list
516d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        if (mRouteInVolumeSliderTouched != null) {
517d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho            mHasPendingUpdate = true;
518d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho            mPendingUpdateAnimationNeeded |= animate;
519d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho            return;
520d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        }
521d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        mHasPendingUpdate = false;
522d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        mPendingUpdateAnimationNeeded = false;
523fa19abbe11335366feb6c885f8d75504ab8fe4f9Insun Kang        if (!mRoute.isSelected() || mRoute.isDefaultOrBluetooth()) {
52411417b1cfde8f1749905f2d735623af9214148afJeff Brown            dismiss();
5257ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
52611417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
52794be6100218126ce6a08bf1f56209578500b361fRoboErik        if (!mCreated) {
5287ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim            return;
52994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
5302ef36d857302c5cd738c7c8bdec53d31feebebbaJeff Brown
5317ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim        mRouteNameTextView.setText(mRoute.getName());
53206991009e52024cbb3dde550988e06149e77a269Jae Seo        mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE);
533d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        if (mCustomControlView == null && mArtIconIsLoaded) {
5347108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            if (isBitmapRecycled(mArtIconLoadedBitmap)) {
5357108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho                Log.w(TAG, "Can't set artwork image with recycled bitmap: " + mArtIconLoadedBitmap);
5367108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            } else {
5377108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho                mArtView.setImageBitmap(mArtIconLoadedBitmap);
5387108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho                mArtView.setBackgroundColor(mArtIconBackgroundColor);
5397108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            }
540d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho            clearLoadedBitmap();
541d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        }
54270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updateVolumeControlLayout();
54370cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updatePlaybackControlLayout();
5441c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        updateLayoutHeight(animate);
5451ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    }
5461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
5477108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho    private boolean isBitmapRecycled(Bitmap bitmap) {
5487108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho        return bitmap != null && bitmap.isRecycled();
5497108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho    }
5507108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho
55170cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private boolean canShowPlaybackControlLayout() {
552eb51f617d95c9a88a6ba528b1ad756f7bb7e7640Jae Seo        return mCustomControlView == null && (mDescription != null || mState != null);
553f043da1f3472ec6f7f4cfe59574aa036b4acdc61Insun Kang    }
554f043da1f3472ec6f7f4cfe59574aa036b4acdc61Insun Kang
5553fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim    /**
5563fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * Returns the height of main media controller which includes playback control and master
5573fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * volume control.
5583fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     */
5592c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    private int getMainControllerHeight(boolean showPlaybackControl) {
5602c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int height = 0;
56170cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        if (showPlaybackControl || mVolumeControlLayout.getVisibility() == View.VISIBLE) {
5622c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            height += mMediaMainControlLayout.getPaddingTop()
5632c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                    + mMediaMainControlLayout.getPaddingBottom();
5642c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (showPlaybackControl) {
56570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                height +=  mPlaybackControlLayout.getMeasuredHeight();
5662c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
56770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            if (mVolumeControlLayout.getVisibility() == View.VISIBLE) {
56870cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                height += mVolumeControlLayout.getMeasuredHeight();
5692c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
57070cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            if (showPlaybackControl && mVolumeControlLayout.getVisibility() == View.VISIBLE) {
5712c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                height += mDividerView.getMeasuredHeight();
5722c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
5732c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
5742c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        return height;
5752c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    }
5762c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
57770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private void updateMediaControlVisibility(boolean canShowPlaybackControlLayout) {
57892fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        // TODO: Update the top and bottom padding of the control layout according to the display
57992fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang        // height.
58070cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        mDividerView.setVisibility((mVolumeControlLayout.getVisibility() == View.VISIBLE
58170cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                && canShowPlaybackControlLayout) ? View.VISIBLE : View.GONE);
58270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        mMediaMainControlLayout.setVisibility((mVolumeControlLayout.getVisibility() == View.GONE
58370cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                && !canShowPlaybackControlLayout) ? View.GONE : View.VISIBLE);
58486dcb627078ea297c4337ed634fc3fe874e23897Jae Seo    }
58586dcb627078ea297c4337ed634fc3fe874e23897Jae Seo
586e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void updateLayoutHeight(final boolean animate) {
58786dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // We need to defer the update until the first layout has occurred, as we don't yet know the
58886dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // overall visible display size in which the window this view is attached to has been
58986dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        // positioned in.
5901c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mDefaultControlLayout.requestLayout();
59186dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        ViewTreeObserver observer = mDefaultControlLayout.getViewTreeObserver();
59286dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
59386dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            @Override
59486dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            public void onGlobalLayout() {
59586dcb627078ea297c4337ed634fc3fe874e23897Jae Seo                mDefaultControlLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
5961c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                if (mIsGroupListAnimating) {
5971c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    mIsGroupListAnimationPending = true;
5981c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                } else {
5991c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    updateLayoutHeightInternal(animate);
6001c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                }
60186dcb627078ea297c4337ed634fc3fe874e23897Jae Seo            }
60286dcb627078ea297c4337ed634fc3fe874e23897Jae Seo        });
60392fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang    }
60492fa1536ded1a81a2b054a08d72b591a13293f99Dongwon Kang
6053fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim    /**
6063fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     * Updates the height of views and hide artwork or metadata if space is limited.
6073fbf2b99dc391c331c2a816e13222a700a1f6dd5Jaewan Kim     */
608e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void updateLayoutHeightInternal(boolean animate) {
60904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        // Measure the size of widgets and get the height of main components.
610c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        int oldHeight = getLayoutHeight(mMediaMainControlLayout);
611e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas        setLayoutHeight(mMediaMainControlLayout, ViewGroup.LayoutParams.MATCH_PARENT);
61270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updateMediaControlVisibility(canShowPlaybackControlLayout());
6132c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        View decorView = getWindow().getDecorView();
6142c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        decorView.measure(
6152c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                MeasureSpec.makeMeasureSpec(getWindow().getAttributes().width, MeasureSpec.EXACTLY),
6162c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                MeasureSpec.UNSPECIFIED);
617c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        setLayoutHeight(mMediaMainControlLayout, oldHeight);
6182c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int artViewHeight = 0;
619fdafcdb0e1c10c02e17085d35ae2861362809e95Dongwon Kang        if (mCustomControlView == null && mArtView.getDrawable() instanceof BitmapDrawable) {
6202c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap();
6212c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            if (art != null) {
6222c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                artViewHeight = getDesiredArtHeight(art.getWidth(), art.getHeight());
6232c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                mArtView.setScaleType(art.getWidth() >= art.getHeight()
6242c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                        ? ImageView.ScaleType.FIT_XY : ImageView.ScaleType.FIT_CENTER);
6252c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            }
6262c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
62770cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        int mainControllerHeight = getMainControllerHeight(canShowPlaybackControlLayout());
6282242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho        int volumeGroupListCount = mGroupMemberRoutes.size();
629c5738b858579021cc89fffd8a891b4c5ea8c0f83Jaewan Kim        // Scale down volume group list items in landscape mode.
6301c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        int expandedGroupListHeight = getGroup() == null ? 0 :
6311c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mVolumeGroupListItemHeight * getGroup().getRoutes().size();
63204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        if (volumeGroupListCount > 0) {
63304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            expandedGroupListHeight += mVolumeGroupListPaddingTop;
63404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        }
63504b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        expandedGroupListHeight = Math.min(expandedGroupListHeight, mVolumeGroupListMaxHeight);
63604b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        int visibleGroupListHeight = mIsGroupExpanded ? expandedGroupListHeight : 0;
63719d268075834665bf62567b224dcd3549c92d3c3Jae Seo
6388367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        int desiredControlLayoutHeight =
63904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang                Math.max(artViewHeight, visibleGroupListHeight) + mainControllerHeight;
6402c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        Rect visibleRect = new Rect();
6412c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        decorView.getWindowVisibleDisplayFrame(visibleRect);
6422c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Height of non-control views in decor view.
6432c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // This includes title bar, button bar, and dialog's vertical padding which should be
6442c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // always shown.
645c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        int nonControlViewHeight = mDialogAreaLayout.getMeasuredHeight()
6462c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                - mDefaultControlLayout.getMeasuredHeight();
6472c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Maximum allowed height for controls to fit screen.
6482c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        int maximumControlViewHeight = visibleRect.height() - nonControlViewHeight;
6492c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
65004b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        // Show artwork if it fits the screen.
651fdafcdb0e1c10c02e17085d35ae2861362809e95Dongwon Kang        if (mCustomControlView == null && artViewHeight > 0
652fdafcdb0e1c10c02e17085d35ae2861362809e95Dongwon Kang                && desiredControlLayoutHeight <= maximumControlViewHeight) {
6532c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            mArtView.setVisibility(View.VISIBLE);
6542c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            setLayoutHeight(mArtView, artViewHeight);
6552c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        } else {
656c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            if (getLayoutHeight(mVolumeGroupList) + mMediaMainControlLayout.getMeasuredHeight()
657c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                    >= mDefaultControlLayout.getMeasuredHeight()) {
658c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                mArtView.setVisibility(View.GONE);
659c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            }
6602c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim            artViewHeight = 0;
66104b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            desiredControlLayoutHeight = visibleGroupListHeight + mainControllerHeight;
6622c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
663c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        // Show the playback control if it fits the screen.
66470cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        if (canShowPlaybackControlLayout()
665f043da1f3472ec6f7f4cfe59574aa036b4acdc61Insun Kang                && desiredControlLayoutHeight <= maximumControlViewHeight) {
66670cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            mPlaybackControlLayout.setVisibility(View.VISIBLE);
6672c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        } else {
66870cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo            mPlaybackControlLayout.setVisibility(View.GONE);
6692c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
67070cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        updateMediaControlVisibility(mPlaybackControlLayout.getVisibility() == View.VISIBLE);
6712c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        mainControllerHeight = getMainControllerHeight(
67270cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                mPlaybackControlLayout.getVisibility() == View.VISIBLE);
6738367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        desiredControlLayoutHeight =
67404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang                Math.max(artViewHeight, visibleGroupListHeight) + mainControllerHeight;
6752c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
6762c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        // Limit the volume group list height to fit the screen.
6778367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim        if (desiredControlLayoutHeight > maximumControlViewHeight) {
67804b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            visibleGroupListHeight -= (desiredControlLayoutHeight - maximumControlViewHeight);
6798367dca195f881c38fbaf69a5d533a6cca820471Jaewan Kim            desiredControlLayoutHeight = maximumControlViewHeight;
6802c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim        }
681c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        // Update the layouts with the computed heights.
682c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mMediaMainControlLayout.clearAnimation();
683c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mVolumeGroupList.clearAnimation();
684c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        mDefaultControlLayout.clearAnimation();
6851c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (animate) {
686c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            animateLayoutHeight(mMediaMainControlLayout, mainControllerHeight);
687c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            animateLayoutHeight(mVolumeGroupList, visibleGroupListHeight);
688c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            animateLayoutHeight(mDefaultControlLayout, desiredControlLayoutHeight);
68904b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        } else {
690c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            setLayoutHeight(mMediaMainControlLayout, mainControllerHeight);
69104b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            setLayoutHeight(mVolumeGroupList, visibleGroupListHeight);
692c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            setLayoutHeight(mDefaultControlLayout, desiredControlLayoutHeight);
69304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        }
694c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        // Maximize the window size with a transparent layout in advance for smooth animation.
695c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        setLayoutHeight(mExpandableAreaLayout, visibleRect.height());
6961c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        rebuildVolumeGroupList(animate);
69704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    }
69804b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang
699e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void updateVolumeGroupItemHeight(View item) {
7001c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        LinearLayout container = (LinearLayout) item.findViewById(R.id.volume_item_container);
7011c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        setLayoutHeight(container, mVolumeGroupListItemHeight);
702d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        View icon = item.findViewById(R.id.mr_volume_item_icon);
703d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        ViewGroup.LayoutParams lp = icon.getLayoutParams();
704d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        lp.width = mVolumeGroupListItemIconSize;
705d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        lp.height = mVolumeGroupListItemIconSize;
706d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim        icon.setLayoutParams(lp);
707d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim    }
708d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim
709c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang    private void animateLayoutHeight(final View view, int targetHeight) {
710c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        final int startValue = getLayoutHeight(view);
711c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        final int endValue = targetHeight;
712c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        Animation anim = new Animation() {
713c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            @Override
714c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang            protected void applyTransformation(float interpolatedTime, Transformation t) {
715c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                int height = startValue - (int) ((startValue - endValue) * interpolatedTime);
716c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang                setLayoutHeight(view, height);
71704b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang            }
718c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        };
719c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        anim.setDuration(mGroupListAnimationDurationMs);
720c38d98f7bcd8effeb4921aeff6f6db8dfdba8de6Dongwon Kang        if (android.os.Build.VERSION.SDK_INT >= 21) {
7211c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            anim.setInterpolator(mInterpolator);
72204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        }
7231c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        view.startAnimation(anim);
7241c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
725af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang
726e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void loadInterpolator() {
7271c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (android.os.Build.VERSION.SDK_INT >= 21) {
7281c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mInterpolator = mIsGroupExpanded ? mLinearOutSlowInInterpolator
7291c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    : mFastOutSlowInInterpolator;
7301c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        } else {
7311c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mInterpolator = mAccelerateDecelerateInterpolator;
732af1dca4a0419eac5d9ff8ecb1c442aacd90d3034Dongwon Kang        }
7332c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim    }
7342c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim
73570cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private void updateVolumeControlLayout() {
736dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim        if (isVolumeControlAvailable(mRoute)) {
737dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim            if (mVolumeControlLayout.getVisibility() == View.GONE) {
73870cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo                mVolumeControlLayout.setVisibility(View.VISIBLE);
7391ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeSlider.setMax(mRoute.getVolumeMax());
7401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                mVolumeSlider.setProgress(mRoute.getVolume());
7411c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mGroupExpandCollapseButton.setVisibility(getGroup() == null ? View.GONE
7421c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        : View.VISIBLE);
7437447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim            }
744dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim        } else {
745dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim            mVolumeControlLayout.setVisibility(View.GONE);
7461ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        }
7471ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim    }
7481ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
7491c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private void rebuildVolumeGroupList(boolean animate) {
7501c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        List<MediaRouter.RouteInfo> routes = getGroup() == null ? null : getGroup().getRoutes();
7511c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (routes == null) {
7521c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mGroupMemberRoutes.clear();
7531c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mVolumeGroupAdapter.notifyDataSetChanged();
7541c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        } else if (MediaRouteDialogHelper.listUnorderedEquals(mGroupMemberRoutes, routes)) {
7551c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mVolumeGroupAdapter.notifyDataSetChanged();
7561c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        } else {
7571c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            HashMap<MediaRouter.RouteInfo, Rect> previousRouteBoundMap = animate
7581c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    ? MediaRouteDialogHelper.getItemBoundMap(mVolumeGroupList, mVolumeGroupAdapter)
7591c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    : null;
7601c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            HashMap<MediaRouter.RouteInfo, BitmapDrawable> previousRouteBitmapMap = animate
7611c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    ? MediaRouteDialogHelper.getItemBitmapMap(mContext, mVolumeGroupList,
7621c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                            mVolumeGroupAdapter) : null;
7631c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mGroupMemberRoutesAdded =
7641c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    MediaRouteDialogHelper.getItemsAdded(mGroupMemberRoutes, routes);
7651c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mGroupMemberRoutesRemoved = MediaRouteDialogHelper.getItemsRemoved(mGroupMemberRoutes,
7661c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    routes);
7671c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mGroupMemberRoutes.addAll(0, mGroupMemberRoutesAdded);
7681c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mGroupMemberRoutes.removeAll(mGroupMemberRoutesRemoved);
7691c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mVolumeGroupAdapter.notifyDataSetChanged();
7701c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            if (animate && mIsGroupExpanded
7711c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    && mGroupMemberRoutesAdded.size() + mGroupMemberRoutesRemoved.size() > 0) {
7721c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                animateGroupListItems(previousRouteBoundMap, previousRouteBitmapMap);
7731c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            } else {
7741c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mGroupMemberRoutesAdded = null;
7751c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mGroupMemberRoutesRemoved = null;
7761c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
7771c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
7781c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
7791c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
7801c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private void animateGroupListItems(final Map<MediaRouter.RouteInfo, Rect> previousRouteBoundMap,
7811c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            final Map<MediaRouter.RouteInfo, BitmapDrawable> previousRouteBitmapMap) {
7821c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mVolumeGroupList.setEnabled(false);
7831c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mVolumeGroupList.requestLayout();
7841c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mIsGroupListAnimating = true;
7851c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        ViewTreeObserver observer = mVolumeGroupList.getViewTreeObserver();
7861c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
7871c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
7881c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onGlobalLayout() {
7891c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mVolumeGroupList.getViewTreeObserver().removeGlobalOnLayoutListener(this);
7901c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                animateGroupListItemsInternal(previousRouteBoundMap, previousRouteBitmapMap);
7911c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
7921c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        });
7931c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
7941c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
795e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void animateGroupListItemsInternal(
7961c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            Map<MediaRouter.RouteInfo, Rect> previousRouteBoundMap,
7971c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            Map<MediaRouter.RouteInfo, BitmapDrawable> previousRouteBitmapMap) {
7981c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (mGroupMemberRoutesAdded == null || mGroupMemberRoutesRemoved == null) {
7991c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            return;
8001c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
8011c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        int groupSizeDelta = mGroupMemberRoutesAdded.size() - mGroupMemberRoutesRemoved.size();
8021c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        boolean listenerRegistered = false;
8031c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        Animation.AnimationListener listener = new Animation.AnimationListener() {
8041c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
8051c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onAnimationStart(Animation animation) {
8061c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mVolumeGroupList.startAnimationAll();
8071c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mVolumeGroupList.postDelayed(mGroupListFadeInAnimation,
8081c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        mGroupListAnimationDurationMs);
8091c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
8101c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
8111c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
8121c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onAnimationEnd(Animation animation) { }
8131c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
8141c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
8151c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onAnimationRepeat(Animation animation) { }
8161c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        };
8171c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
8181c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        // Animate visible items from previous positions to current positions except routes added
8191c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        // just before. Added routes will remain hidden until translate animation finishes.
8201c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        int first = mVolumeGroupList.getFirstVisiblePosition();
8211c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
8221c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            View view = mVolumeGroupList.getChildAt(i);
8231c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            int position = first + i;
8241c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            MediaRouter.RouteInfo route = mVolumeGroupAdapter.getItem(position);
8251c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            Rect previousBounds = previousRouteBoundMap.get(route);
8261c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            int currentTop = view.getTop();
8271c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            int previousTop = previousBounds != null ? previousBounds.top
8281c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    : (currentTop + mVolumeGroupListItemHeight * groupSizeDelta);
8291c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            AnimationSet animSet = new AnimationSet(true);
8301c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            if (mGroupMemberRoutesAdded != null && mGroupMemberRoutesAdded.contains(route)) {
8311c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                previousTop = currentTop;
8321c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                Animation alphaAnim = new AlphaAnimation(0.0f, 0.0f);
8331c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                alphaAnim.setDuration(mGroupListFadeInDurationMs);
8341c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                animSet.addAnimation(alphaAnim);
8351c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
8361c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            Animation translationAnim = new TranslateAnimation(0, 0, previousTop - currentTop, 0);
8371c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            translationAnim.setDuration(mGroupListAnimationDurationMs);
8381c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            animSet.addAnimation(translationAnim);
8391c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            animSet.setFillAfter(true);
8401c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            animSet.setFillEnabled(true);
8411c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            animSet.setInterpolator(mInterpolator);
8421c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            if (!listenerRegistered) {
8431c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                listenerRegistered = true;
8441c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                animSet.setAnimationListener(listener);
8451c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
8461c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            view.clearAnimation();
8471c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            view.startAnimation(animSet);
8481c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            previousRouteBoundMap.remove(route);
8491c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            previousRouteBitmapMap.remove(route);
8501c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
8511c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
8521c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        // If a member route doesn't exist any longer, it can be either removed or moved out of the
8531c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        // ListView layout boundary. In this case, use the previously captured bitmaps for
8541c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        // animation.
8551c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        for (Map.Entry<MediaRouter.RouteInfo, BitmapDrawable> item
8561c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                : previousRouteBitmapMap.entrySet()) {
8571c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            final MediaRouter.RouteInfo route = item.getKey();
8581c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            final BitmapDrawable bitmap = item.getValue();
8591c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            final Rect bounds = previousRouteBoundMap.get(route);
860ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas            OverlayListView.OverlayObject object = null;
8611c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            if (mGroupMemberRoutesRemoved.contains(route)) {
862ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                object = new OverlayListView.OverlayObject(bitmap, bounds).setAlphaAnimation(1.0f, 0.0f)
8631c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        .setDuration(mGroupListFadeOutDurationMs)
8641c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        .setInterpolator(mInterpolator);
8651c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            } else {
8661c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                int deltaY = groupSizeDelta * mVolumeGroupListItemHeight;
867ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                object = new OverlayListView.OverlayObject(bitmap, bounds).setTranslateYAnimation(deltaY)
8681c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        .setDuration(mGroupListAnimationDurationMs)
8691c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        .setInterpolator(mInterpolator)
870ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas                        .setAnimationEndListener(new OverlayListView.OverlayObject.OnAnimationEndListener() {
8711c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                            @Override
8721c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                            public void onAnimationEnd() {
8731c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                                mGroupMemberRoutesAnimatingWithBitmap.remove(route);
8741c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                                mVolumeGroupAdapter.notifyDataSetChanged();
8751c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                            }
8761c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        });
8771c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mGroupMemberRoutesAnimatingWithBitmap.add(route);
8781c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
8791c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mVolumeGroupList.addOverlayObject(object);
8801c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
8811c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
8821c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
883e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void startGroupListFadeInAnimation() {
8841c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        clearGroupListAnimation(true);
8851c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mVolumeGroupList.requestLayout();
8861c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        ViewTreeObserver observer = mVolumeGroupList.getViewTreeObserver();
8871c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
8881c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
8891c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onGlobalLayout() {
8901c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                mVolumeGroupList.getViewTreeObserver().removeGlobalOnLayoutListener(this);
8911c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                startGroupListFadeInAnimationInternal();
8921c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
8931c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        });
8941c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
8951c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
896e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void startGroupListFadeInAnimationInternal() {
8971c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (mGroupMemberRoutesAdded != null && mGroupMemberRoutesAdded.size() != 0) {
8981c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            fadeInAddedRoutes();
8991c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        } else {
9001c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            finishAnimation(true);
9011c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
9021c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
9031c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
904e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void finishAnimation(boolean animate) {
9051c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mGroupMemberRoutesAdded = null;
9061c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mGroupMemberRoutesRemoved = null;
9071c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mIsGroupListAnimating = false;
9081c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (mIsGroupListAnimationPending) {
9091c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            mIsGroupListAnimationPending = false;
9101c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            updateLayoutHeight(animate);
9111c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
9121c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mVolumeGroupList.setEnabled(true);
9131c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
9141c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
9151c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    private void fadeInAddedRoutes() {
9161c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        Animation.AnimationListener listener = new Animation.AnimationListener() {
9171c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
9181c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onAnimationStart(Animation animation) { }
9191c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
9201c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
9211c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onAnimationEnd(Animation animation) {
9221c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                finishAnimation(true);
9231c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
9241c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
9251c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            @Override
9261c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            public void onAnimationRepeat(Animation animation) { }
9271c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        };
9281c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        boolean listenerRegistered = false;
9291c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        int first = mVolumeGroupList.getFirstVisiblePosition();
9301c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
9311c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            View view = mVolumeGroupList.getChildAt(i);
9321c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            int position = first + i;
9331c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            MediaRouter.RouteInfo route = mVolumeGroupAdapter.getItem(position);
9341c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            if (mGroupMemberRoutesAdded.contains(route)) {
9351c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                Animation alphaAnim = new AlphaAnimation(0.0f, 1.0f);
9361c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                alphaAnim.setDuration(mGroupListFadeInDurationMs);
9371c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                alphaAnim.setFillEnabled(true);
9381c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                alphaAnim.setFillAfter(true);
9391c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                if (!listenerRegistered) {
9401c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    listenerRegistered = true;
9411c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    alphaAnim.setAnimationListener(listener);
9421c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                }
9431c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                view.clearAnimation();
9441c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                view.startAnimation(alphaAnim);
9451c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
9461c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
9471c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    }
9481c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
9491c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho    void clearGroupListAnimation(boolean exceptAddedRoutes) {
9501c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        int first = mVolumeGroupList.getFirstVisiblePosition();
9511c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
9521c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            View view = mVolumeGroupList.getChildAt(i);
9531c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            int position = first + i;
9541c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            MediaRouter.RouteInfo route = mVolumeGroupAdapter.getItem(position);
9551c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            if (exceptAddedRoutes && mGroupMemberRoutesAdded != null
9561c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    && mGroupMemberRoutesAdded.contains(route)) {
9571c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                continue;
9581c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            }
9591c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            LinearLayout container = (LinearLayout) view.findViewById(R.id.volume_item_container);
9601c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            container.setVisibility(View.VISIBLE);
9611c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            AnimationSet animSet = new AnimationSet(true);
9621c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            Animation alphaAnim = new AlphaAnimation(1.0f, 1.0f);
9631c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            alphaAnim.setDuration(0);
9641c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            animSet.addAnimation(alphaAnim);
9651c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            Animation translationAnim = new TranslateAnimation(0, 0, 0, 0);
9661c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            translationAnim.setDuration(0);
9671c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            animSet.setFillAfter(true);
9681c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            animSet.setFillEnabled(true);
9691c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            view.clearAnimation();
9701c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            view.startAnimation(animSet);
9711c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        }
9721c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        mVolumeGroupList.stopAnimationAll();
9731c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho        if (!exceptAddedRoutes) {
9741c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            finishAnimation(false);
9752242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho        }
9762242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho    }
9772242344e6d1a2fe48c99926c39a87d1e0e4326cfDonghyun Cho
97870cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo    private void updatePlaybackControlLayout() {
97970cae05dea9dc5bb23200e27d02fd0d9cf2d4b5bJae Seo        if (canShowPlaybackControlLayout()) {
9801ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            CharSequence title = mDescription == null ? null : mDescription.getTitle();
9811ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            boolean hasTitle = !TextUtils.isEmpty(title);
9821ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
9831ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle();
9841ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            boolean hasSubtitle = !TextUtils.isEmpty(subtitle);
9851ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim
9868fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            boolean showTitle = false;
9878fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            boolean showSubtitle = false;
9888fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            if (mRoute.getPresentationDisplayId()
9898fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) {
9908fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                // The user is currently casting screen.
9918fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_casting_screen);
9928fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
9938fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            } else if (mState == null || mState.getState() == PlaybackStateCompat.STATE_NONE) {
994eb51f617d95c9a88a6ba528b1ad756f7bb7e7640Jae Seo                // Show "No media selected" as we don't yet know the playback state.
995fa19abbe11335366feb6c885f8d75504ab8fe4f9Insun Kang                mTitleView.setText(R.string.mr_controller_no_media_selected);
996fa19abbe11335366feb6c885f8d75504ab8fe4f9Insun Kang                showTitle = true;
9978fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            } else if (!hasTitle && !hasSubtitle) {
9988fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                mTitleView.setText(R.string.mr_controller_no_info_available);
9998fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                showTitle = true;
10001ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else {
10018fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                if (hasTitle) {
10028fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    mTitleView.setText(title);
10038fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    showTitle = true;
10048fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                }
10058fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                if (hasSubtitle) {
10068fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    mSubtitleView.setText(subtitle);
10078fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                    showSubtitle = true;
10088fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang                }
10091ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
10108fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            mTitleView.setVisibility(showTitle ? View.VISIBLE : View.GONE);
10118fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang            mSubtitleView.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
10128fd7b051e85d46381b5b8afd3d4b569d155ac48eInsun Kang
10131ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            if (mState != null) {
10141ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
10151ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                        || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
10166a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                Context playbackControlButtonContext = mPlaybackControlButton.getContext();
10176a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                boolean visible = true;
10186a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                int iconDrawableAttr = 0;
10196a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                int iconDescResId = 0;
10206a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                if (isPlaying && isPauseActionSupported()) {
10216a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    iconDrawableAttr = R.attr.mediaRoutePauseDrawable;
10226a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    iconDescResId = R.string.mr_controller_pause;
10236a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                } else if (isPlaying && isStopActionSupported()) {
10246a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    iconDrawableAttr = R.attr.mediaRouteStopDrawable;
10256a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    iconDescResId = R.string.mr_controller_stop;
10266a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                } else if (!isPlaying && isPlayActionSupported()) {
10276a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    iconDrawableAttr = R.attr.mediaRoutePlayDrawable;
10286a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    iconDescResId = R.string.mr_controller_play;
10291ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                } else {
10306a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    visible = false;
10316a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                }
10326a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                mPlaybackControlButton.setVisibility(visible ? View.VISIBLE : View.GONE);
10336a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                if (visible) {
10346a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    mPlaybackControlButton.setImageResource(
10356a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                            MediaRouterThemeHelper.getThemeResource(
10366a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                                    playbackControlButtonContext, iconDrawableAttr));
10376a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    mPlaybackControlButton.setContentDescription(
10386a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                            playbackControlButtonContext.getResources()
10396a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                                    .getText(iconDescResId));
10401ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim                }
10411ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            }
10421ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim        }
10432b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang    }
10442b274bd3e06bd33c9b2a0851256afcda94d96395Dongwon Kang
10456a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho    private boolean isPlayActionSupported() {
10466a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho        return (mState.getActions() & (ACTION_PLAY | ACTION_PLAY_PAUSE)) != 0;
10476a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho    }
10486a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho
10496a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho    private boolean isPauseActionSupported() {
10506a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho        return (mState.getActions() & (ACTION_PAUSE | ACTION_PLAY_PAUSE)) != 0;
10516a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho    }
10526a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho
10536a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho    private boolean isStopActionSupported() {
10546a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho        return (mState.getActions() & ACTION_STOP) != 0;
10556a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho    }
10566a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho
1057e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    boolean isVolumeControlAvailable(MediaRouter.RouteInfo route) {
10587447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim        return mVolumeControlEnabled && route.getVolumeHandling()
10597447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
1060f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah    }
1061f1ca2f34f5efed21a49d92dd06e8e51be104c10bPrameet Shah
106204b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    private static int getLayoutHeight(View view) {
106304b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang        return view.getLayoutParams().height;
106404b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang    }
106504b31a042cb2c18ffe6ccfba7309f6b8222678cdDongwon Kang
1066e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    static void setLayoutHeight(View view, int height) {
1067be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        ViewGroup.LayoutParams lp = view.getLayoutParams();
1068be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        lp.height = height;
1069be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang        view.setLayoutParams(lp);
1070be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang    }
1071be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang
1072376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho    private static boolean uriEquals(Uri uri1, Uri uri2) {
1073376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho        if (uri1 != null && uri1.equals(uri2)) {
1074376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            return true;
1075376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho        } else if (uri1 == null && uri2 == null) {
1076376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            return true;
1077376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho        }
1078376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho        return false;
1079376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho    }
1080376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho
108113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    /**
108213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     * Returns desired art height to fit into controller dialog.
108313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim     */
1084e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    int getDesiredArtHeight(int originalWidth, int originalHeight) {
108513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        if (originalWidth >= originalHeight) {
108613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            // For landscape art, fit width to dialog width.
1087f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo            return (int) ((float) mDialogContentWidth * originalHeight / originalWidth + 0.5f);
108813d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        }
108913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        // For portrait art, fit height to 16:9 ratio case's height.
1090f4575634e9f3c2b61c2e6bceaeed6cabb378803fJae Seo        return (int) ((float) mDialogContentWidth * 9 / 16 + 0.5f);
109113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim    }
109213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim
1093e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void updateArtIconIfNeeded() {
109475322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        if (mCustomControlView != null || !isIconChanged()) {
109575322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho            return;
109675322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        }
109775322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        if (mFetchArtTask != null) {
109875322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho            mFetchArtTask.cancel(true);
109975322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        }
110075322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        mFetchArtTask = new FetchArtTask();
110175322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        mFetchArtTask.execute();
110275322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho    }
110375322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho
110475322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho    /**
1105d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho     * Clear the bitmap loaded by FetchArtTask. Will be called after the loaded bitmaps are applied
1106d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho     * to artwork, or no longer valid.
1107d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho     */
1108e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas    void clearLoadedBitmap() {
1109d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        mArtIconIsLoaded = false;
1110d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        mArtIconLoadedBitmap = null;
1111d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho        mArtIconBackgroundColor = 0;
1112d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho    }
1113d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho
1114d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho    /**
111575322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho     * Returns whether a new art image is different from an original art image. Compares
111675322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho     * Bitmap objects first, and then compares URIs only if bitmap is unchanged with
111775322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho     * a null value.
111875322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho     */
111975322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho    private boolean isIconChanged() {
112075322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        Bitmap newBitmap = mDescription == null ? null : mDescription.getIconBitmap();
112175322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        Uri newUri = mDescription == null ? null : mDescription.getIconUri();
112275322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        Bitmap oldBitmap = mFetchArtTask == null ? mArtIconBitmap : mFetchArtTask.getIconBitmap();
112375322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        Uri oldUri = mFetchArtTask == null ? mArtIconUri : mFetchArtTask.getIconUri();
112475322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        if (oldBitmap != newBitmap) {
112575322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho            return true;
112675322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        } else if (oldBitmap == null && !uriEquals(oldUri, newUri)) {
112775322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho            return true;
112875322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        }
112975322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        return false;
113075322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho    }
113175322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho
113211417b1cfde8f1749905f2d735623af9214148afJeff Brown    private final class MediaRouterCallback extends MediaRouter.Callback {
1133e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        MediaRouterCallback() {
1134e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        }
1135e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
113611417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
113711417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
11381c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            update(false);
113911417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
114011417b1cfde8f1749905f2d735623af9214148afJeff Brown
114111417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
114211417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
11431c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            update(true);
114411417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
114511417b1cfde8f1749905f2d735623af9214148afJeff Brown
114611417b1cfde8f1749905f2d735623af9214148afJeff Brown        @Override
114711417b1cfde8f1749905f2d735623af9214148afJeff Brown        public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
1148dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim            SeekBar volumeSlider = mVolumeSliderMap.get(route);
1149ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang            int volume = route.getVolume();
1150ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang            if (DEBUG) {
1151ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang                Log.d(TAG, "onRouteVolumeChanged(), route.getVolume:" + volume);
1152ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang            }
1153dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim            if (volumeSlider != null && mRouteInVolumeSliderTouched != route) {
1154ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang                volumeSlider.setProgress(volume);
115594be6100218126ce6a08bf1f56209578500b361fRoboErik            }
115694be6100218126ce6a08bf1f56209578500b361fRoboErik        }
115794be6100218126ce6a08bf1f56209578500b361fRoboErik    }
115894be6100218126ce6a08bf1f56209578500b361fRoboErik
115994be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class MediaControllerCallback extends MediaControllerCompat.Callback {
1160e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        MediaControllerCallback() {
1161e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        }
1162e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
116394be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
116494be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onSessionDestroyed() {
116594be6100218126ce6a08bf1f56209578500b361fRoboErik            if (mMediaController != null) {
116694be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController.unregisterCallback(mControllerCallback);
116794be6100218126ce6a08bf1f56209578500b361fRoboErik                mMediaController = null;
116894be6100218126ce6a08bf1f56209578500b361fRoboErik            }
116994be6100218126ce6a08bf1f56209578500b361fRoboErik        }
117094be6100218126ce6a08bf1f56209578500b361fRoboErik
117194be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
117294be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onPlaybackStateChanged(PlaybackStateCompat state) {
117394be6100218126ce6a08bf1f56209578500b361fRoboErik            mState = state;
11741c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            update(false);
117594be6100218126ce6a08bf1f56209578500b361fRoboErik        }
117694be6100218126ce6a08bf1f56209578500b361fRoboErik
117794be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
117894be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onMetadataChanged(MediaMetadataCompat metadata) {
117994be6100218126ce6a08bf1f56209578500b361fRoboErik            mDescription = metadata == null ? null : metadata.getDescription();
118075322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho            updateArtIconIfNeeded();
11811c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho            update(false);
118294be6100218126ce6a08bf1f56209578500b361fRoboErik        }
118394be6100218126ce6a08bf1f56209578500b361fRoboErik    }
118494be6100218126ce6a08bf1f56209578500b361fRoboErik
118594be6100218126ce6a08bf1f56209578500b361fRoboErik    private final class ClickListener implements View.OnClickListener {
1186e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        ClickListener() {
1187e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        }
1188e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
118994be6100218126ce6a08bf1f56209578500b361fRoboErik        @Override
119094be6100218126ce6a08bf1f56209578500b361fRoboErik        public void onClick(View v) {
119194be6100218126ce6a08bf1f56209578500b361fRoboErik            int id = v.getId();
119206991009e52024cbb3dde550988e06149e77a269Jae Seo            if (id == BUTTON_STOP_RES_ID || id == BUTTON_DISCONNECT_RES_ID) {
119394be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mRoute.isSelected()) {
119406991009e52024cbb3dde550988e06149e77a269Jae Seo                    mRouter.unselect(id == BUTTON_STOP_RES_ID ?
119594be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_STOPPED :
119694be6100218126ce6a08bf1f56209578500b361fRoboErik                            MediaRouter.UNSELECT_REASON_DISCONNECTED);
119794be6100218126ce6a08bf1f56209578500b361fRoboErik                }
119894be6100218126ce6a08bf1f56209578500b361fRoboErik                dismiss();
11996a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho            } else if (id == R.id.mr_control_playback_ctrl) {
120094be6100218126ce6a08bf1f56209578500b361fRoboErik                if (mMediaController != null && mState != null) {
1201ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_PLAYING;
12026a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    int actionDescResId = 0;
12036a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    if (isPlaying && isPauseActionSupported()) {
120494be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().pause();
12056a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                        actionDescResId = R.string.mr_controller_pause;
12066a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    } else if (isPlaying && isStopActionSupported()) {
12076a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                        mMediaController.getTransportControls().stop();
12086a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                        actionDescResId = R.string.mr_controller_stop;
12096a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    } else if (!isPlaying && isPlayActionSupported()){
121094be6100218126ce6a08bf1f56209578500b361fRoboErik                        mMediaController.getTransportControls().play();
12116a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                        actionDescResId = R.string.mr_controller_play;
121294be6100218126ce6a08bf1f56209578500b361fRoboErik                    }
1213ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    // Announce the action for accessibility.
12146a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                    if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()
12156a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                            && actionDescResId != 0) {
1216ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                        AccessibilityEvent event = AccessibilityEvent.obtain(
1217ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                                AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
12184c5deffa8ddeb34accfded51e2be8573fbc1f301Dongwon Kang                        event.setPackageName(mContext.getPackageName());
1219ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                        event.setClassName(getClass().getName());
12206a39e73d20f14bed34f6bd9bc61b5b59d5050477Donghyun Cho                        event.getText().add(mContext.getString(actionDescResId));
1221ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                        mAccessibilityManager.sendAccessibilityEvent(event);
1222ee7ae661b02471fe598566b1e90adbacda240b0bJae Seo                    }
122394be6100218126ce6a08bf1f56209578500b361fRoboErik                }
12241ce169ba80c2047846dca5ee8c723faadcd1da86Sungsoo Lim            } else if (id == R.id.mr_close) {
1225b48ccf48b0281e69262fc643d0def898aede407bSungsoo Lim                dismiss();
122611417b1cfde8f1749905f2d735623af9214148afJeff Brown            }
122711417b1cfde8f1749905f2d735623af9214148afJeff Brown        }
122811417b1cfde8f1749905f2d735623af9214148afJeff Brown    }
1229005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
1230dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim    private class VolumeChangeListener implements SeekBar.OnSeekBarChangeListener {
1231435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        private final Runnable mStopTrackingTouch = new Runnable() {
12326051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            @Override
1233435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            public void run() {
1234dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim                if (mRouteInVolumeSliderTouched != null) {
1235dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim                    mRouteInVolumeSliderTouched = null;
1236d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                    if (mHasPendingUpdate) {
1237d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                        update(mPendingUpdateAnimationNeeded);
1238d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                    }
12396051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo                }
12406051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
1241435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        };
12426051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
1243e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        VolumeChangeListener() {
1244e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas        }
1245e2c6a94b6e4aab502f9b88dd3ff664bd90b25839Aurimas Liutikas
1246435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
1247435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onStartTrackingTouch(SeekBar seekBar) {
1248dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim            if (mRouteInVolumeSliderTouched != null) {
1249435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                mVolumeSlider.removeCallbacks(mStopTrackingTouch);
12506051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
1251dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim            mRouteInVolumeSliderTouched = (MediaRouter.RouteInfo) seekBar.getTag();
1252435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
12536051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
1254435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
1255435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onStopTrackingTouch(SeekBar seekBar) {
1256435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // Defer resetting mVolumeSliderTouched to allow the media route provider
1257435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // a little time to settle into its new state and publish the final
1258435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            // volume update.
1259435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
1260435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
1261435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim
1262435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        @Override
1263435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
1264435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim            if (fromUser) {
1265dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim                MediaRouter.RouteInfo route = (MediaRouter.RouteInfo) seekBar.getTag();
1266ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang                if (DEBUG) {
1267ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang                    Log.d(TAG, "onProgressChanged(): calling "
1268ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang                            + "MediaRouter.RouteInfo.requestSetVolume(" + progress + ")");
1269435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                }
1270ddec4bb519422d680d93911e95d252b620d09ba2Insun Kang                route.requestSetVolume(progress);
12716051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
1272435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim        }
1273435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    }
1274435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim
1275435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim    private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> {
1276d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo        final float mDisabledAlpha;
12776051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
12786051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) {
12796051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            super(context, 0, objects);
1280d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo            mDisabledAlpha = MediaRouterThemeHelper.getDisabledAlpha(context);
12816051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
12826051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
12836051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        @Override
12843b2841ba851902b0516ed8a2178a0d92c0a8b923Hyundo Moon        public boolean isEnabled(int position) {
12853b2841ba851902b0516ed8a2178a0d92c0a8b923Hyundo Moon            return false;
12863b2841ba851902b0516ed8a2178a0d92c0a8b923Hyundo Moon        }
12873b2841ba851902b0516ed8a2178a0d92c0a8b923Hyundo Moon
12883b2841ba851902b0516ed8a2178a0d92c0a8b923Hyundo Moon        @Override
12896051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        public View getView(final int position, View convertView, ViewGroup parent) {
12906051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            View v = convertView;
12916051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (v == null) {
1292166da1fa21cc24216730da32c9b81c591349db87Donghyun Cho                v = LayoutInflater.from(parent.getContext()).inflate(
12932c8c38b6c0d4302b4a6537b972c905c4fc8dd3e0Jaewan Kim                        R.layout.mr_controller_volume_item, parent, false);
1294d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim            } else {
1295d5500b7822bfca5997827ec4c1c058dcab969c60Jaewan Kim                updateVolumeGroupItemHeight(v);
12966051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
129719d268075834665bf62567b224dcd3549c92d3c3Jae Seo
12986051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            MediaRouter.RouteInfo route = getItem(position);
12996051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            if (route != null) {
13000e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                boolean isEnabled = route.isEnabled();
13010e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
13027ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                TextView routeName = (TextView) v.findViewById(R.id.mr_name);
13030e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setEnabled(isEnabled);
13040e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                routeName.setText(route.getName());
13056051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
1306ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                MediaRouteVolumeSlider volumeSlider =
1307ea15dd5d0313d55452f552d8583eb230b2c9506fJaewan Kim                        (MediaRouteVolumeSlider) v.findViewById(R.id.mr_volume_slider);
1308d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                MediaRouterThemeHelper.setVolumeSliderColor(
1309166da1fa21cc24216730da32c9b81c591349db87Donghyun Cho                        parent.getContext(), volumeSlider, mVolumeGroupList);
1310dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim                volumeSlider.setTag(route);
1311dbe6b4010999eaa31c5bbac520277391717c2ef0Sungsoo Lim                mVolumeSliderMap.put(route, volumeSlider);
13120b72510d7bc402b71065e069852d10a8592d55deJaewan Kim                volumeSlider.setHideThumb(!isEnabled);
1313d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                volumeSlider.setEnabled(isEnabled);
13140e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                if (isEnabled) {
13157447b1958129579090ee279caac7d703dba2ad28Sungsoo Lim                    if (isVolumeControlAvailable(route)) {
13160e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(route.getVolumeMax());
13170e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(route.getVolume());
1318435661b8ed5ba59ef5d78cf10fbbf005bf62b895Sungsoo Lim                        volumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
13190e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    } else {
13200e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setMax(100);
13210e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setProgress(100);
13220e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                        volumeSlider.setEnabled(false);
13230e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                    }
13240e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                }
13250e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo
13260e36aa71ffed511f5ad6b0a24e75ccf651e43c40Jae Seo                ImageView volumeItemIcon =
13277ff59b631bd798bdf0c6647d1279a08a33c62977Sungsoo Lim                        (ImageView) v.findViewById(R.id.mr_volume_item_icon);
1328d807ca0f601dc0b9807e0ed635b3f502fddec083Jae Seo                volumeItemIcon.setAlpha(isEnabled ? 0xFF : (int) (0xFF * mDisabledAlpha));
13291c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
13301c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                // If overlay bitmap exists, real view should remain hidden until
13311c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                // the animation ends.
13321c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                LinearLayout container = (LinearLayout) v.findViewById(R.id.volume_item_container);
13331c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                container.setVisibility(mGroupMemberRoutesAnimatingWithBitmap.contains(route)
13341c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                        ? View.INVISIBLE : View.VISIBLE);
13351c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho
13361c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                // Routes which are being added will be invisible until animation ends.
13371c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                if (mGroupMemberRoutesAdded != null && mGroupMemberRoutesAdded.contains(route)) {
13381c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    Animation alphaAnim = new AlphaAnimation(0.0f, 0.0f);
13391c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    alphaAnim.setDuration(0);
13401c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    alphaAnim.setFillEnabled(true);
13411c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    alphaAnim.setFillAfter(true);
13421c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    v.clearAnimation();
13431c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                    v.startAnimation(alphaAnim);
13441c4fce94062e162e579d20134f0bac767bdf0964Donghyun Cho                }
13456051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            }
13466051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo            return v;
13476051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo        }
13486051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo    }
13496051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo
1350005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> {
135187654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho        // Show animation only when fetching takes a long time.
135287654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho        private static final long SHOW_ANIM_TIME_THRESHOLD_MILLIS = 120L;
135387654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho
135487654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho        private final Bitmap mIconBitmap;
135587654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho        private final Uri mIconUri;
135687654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho        private int mBackgroundColor;
135787654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho        private long mStartTimeMillis;
13588bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
13598bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        FetchArtTask() {
13607108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            Bitmap bitmap = mDescription == null ? null : mDescription.getIconBitmap();
13617108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            if (isBitmapRecycled(bitmap)) {
13627108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho                Log.w(TAG, "Can't fetch the given art bitmap because it's already recycled.");
13637108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho                bitmap = null;
13647108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            }
13657108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            mIconBitmap = bitmap;
13668bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            mIconUri = mDescription == null ? null : mDescription.getIconUri();
13678bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        }
13688bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo
136975322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        public Bitmap getIconBitmap() {
137075322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho            return mIconBitmap;
137175322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        }
137275322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho
137375322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        public Uri getIconUri() {
137475322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho            return mIconUri;
137575322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho        }
137675322d1d57085c80a76d0d6db41426777dab08d0Donghyun Cho
13778bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        @Override
13788bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        protected void onPreExecute() {
137987654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho            mStartTimeMillis = SystemClock.uptimeMillis();
1380d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho            clearLoadedBitmap();
13818bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo        }
1382005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
1383005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
1384005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        protected Bitmap doInBackground(Void... arg) {
138513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            Bitmap art = null;
13868bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            if (mIconBitmap != null) {
13878bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                art = mIconBitmap;
13888bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            } else if (mIconUri != null) {
1389376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                InputStream stream = null;
1390005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                try {
1391376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                    if ((stream = openInputStreamByScheme(mIconUri)) == null) {
1392376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                        Log.w(TAG, "Unable to open: " + mIconUri);
1393376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                        return null;
1394376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                    }
139513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Query art size.
1396005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.Options options = new BitmapFactory.Options();
1397005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = true;
1398005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    BitmapFactory.decodeStream(stream, null, options);
139913d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    if (options.outWidth == 0 || options.outHeight == 0) {
140013d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                        return null;
140113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    }
140213d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Rewind the stream in order to restart art decoding.
1403005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    try {
1404005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.reset();
1405005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    } catch (IOException e) {
1406005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        // Failed to rewind the stream, try to reopen it.
1407005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        stream.close();
1408376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                        if ((stream = openInputStreamByScheme(mIconUri)) == null) {
1409376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                            Log.w(TAG, "Unable to open: " + mIconUri);
1410376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                            return null;
1411376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                        }
1412005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
141313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    // Calculate required size to decode the art and possibly resize it.
1414005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inJustDecodeBounds = false;
141513d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight);
141613d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    int ratio = options.outHeight / reqHeight;
1417005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio));
1418005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (isCancelled()) {
1419005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        return null;
1420005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
142113d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim                    art = BitmapFactory.decodeStream(stream, null, options);
1422005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } catch (IOException e){
14238bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                    Log.w(TAG, "Unable to open: " + mIconUri, e);
1424005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                } finally {
1425005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    if (stream != null) {
1426005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        try {
1427005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                            stream.close();
1428005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        } catch (IOException e) {
1429005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                        }
1430005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                    }
1431005482649154d0970693b3967241eb4d2cb22003Jaewan Kim                }
1432005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
14337108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            if (isBitmapRecycled(art)) {
14347108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho                Log.w(TAG, "Can't use recycled bitmap: " + art);
14357108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho                return null;
14367108a5f54fd0db0639a140d320f5d4e85975ac23Donghyun Cho            }
1437145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim            if (art != null && art.getWidth() < art.getHeight()) {
1438c4c371f91673a882177f16fa95723e7e69f54882Insun Kang                // Portrait art requires dominant color as background color.
1439145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                Palette palette = new Palette.Builder(art).maximumColorCount(1).generate();
1440be6358a7c928a09f2c767524299f86a8aad84558Dongwon Kang                mBackgroundColor = palette.getSwatches().isEmpty()
1441145e93b13dd025b278665494e7be0c15b8df5986Jaewan Kim                        ? 0 : palette.getSwatches().get(0).getRgb();
1442005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            }
144313d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim            return art;
1444005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
1445005482649154d0970693b3967241eb4d2cb22003Jaewan Kim
1446005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        @Override
144713d6fb598d2270bed0dbcdb8d66d012382780f53Jaewan Kim        protected void onPostExecute(Bitmap art) {
1448005482649154d0970693b3967241eb4d2cb22003Jaewan Kim            mFetchArtTask = null;
1449c9bbadfa70a2a3f92bd497bf1ed6f7586f758ce6Alan Viverette            if (!ObjectsCompat.equals(mArtIconBitmap, mIconBitmap)
1450c9bbadfa70a2a3f92bd497bf1ed6f7586f758ce6Alan Viverette                    || !ObjectsCompat.equals(mArtIconUri, mIconUri)) {
14518bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtIconBitmap = mIconBitmap;
1452d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                mArtIconLoadedBitmap = art;
14538bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo                mArtIconUri = mIconUri;
1454d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                mArtIconBackgroundColor = mBackgroundColor;
1455d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                mArtIconIsLoaded = true;
145687654ffe5c675519fd2a611c8fad40ee0979011eDonghyun Cho                long elapsedTimeMillis = SystemClock.uptimeMillis() - mStartTimeMillis;
1457d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                // Loaded bitmap will be applied on the next update
1458d50585ab0e5ccd0ae70a55652deb7bcb3c2d3c56Donghyun Cho                update(elapsedTimeMillis > SHOW_ANIM_TIME_THRESHOLD_MILLIS);
14598bc60d9260a4b31356fceb31264a47b55f6114f4Jae Seo            }
1460005482649154d0970693b3967241eb4d2cb22003Jaewan Kim        }
1461376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho
1462376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho        private InputStream openInputStreamByScheme(Uri uri) throws IOException {
1463376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            String scheme = uri.getScheme().toLowerCase();
1464376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            InputStream stream = null;
1465376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
1466376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                    || ContentResolver.SCHEME_CONTENT.equals(scheme)
1467376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                    || ContentResolver.SCHEME_FILE.equals(scheme)) {
1468376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                stream = mContext.getContentResolver().openInputStream(uri);
1469376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            } else {
1470376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                URL url = new URL(uri.toString());
1471376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                URLConnection conn = url.openConnection();
1472376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                conn.setConnectTimeout(CONNECTION_TIMEOUT_MILLIS);
1473376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                conn.setReadTimeout(CONNECTION_TIMEOUT_MILLIS);
1474376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho                stream = conn.getInputStream();
1475376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            }
1476376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho            return (stream == null) ? null : new BufferedInputStream(stream);
1477376f4d5a03a3dfc9d4ca30074b3df3e424bd7e4bDonghyun Cho        }
1478005482649154d0970693b3967241eb4d2cb22003Jaewan Kim    }
14796051d8374c90da4826698b66ed7cb13ebc2c65bfJae Seo}
1480