1692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim/*
2692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * Copyright 2018 The Android Open Source Project
3692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *
4692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * Licensed under the Apache License, Version 2.0 (the "License");
5692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * you may not use this file except in compliance with the License.
6692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * You may obtain a copy of the License at
7692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *
8692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *      http://www.apache.org/licenses/LICENSE-2.0
9692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *
10692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * Unless required by applicable law or agreed to in writing, software
11692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * distributed under the License is distributed on an "AS IS" BASIS,
12692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * See the License for the specific language governing permissions and
14692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * limitations under the License.
15692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim */
16692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
17692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limpackage com.android.support.mediarouter.app;
18692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
19692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_PAUSE;
20692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY;
21692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_PLAY_PAUSE;
22692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport static android.support.v4.media.session.PlaybackStateCompat.ACTION_STOP;
23692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
24d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Limimport android.app.AlertDialog;
25692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.app.PendingIntent;
26692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.content.ContentResolver;
27692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.content.Context;
28692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.content.res.Resources;
29692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.graphics.Bitmap;
30692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.graphics.BitmapFactory;
31692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.graphics.Rect;
32692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.graphics.drawable.BitmapDrawable;
33692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.net.Uri;
34692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.os.AsyncTask;
35692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.os.Bundle;
36692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.os.RemoteException;
37692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.os.SystemClock;
38692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v4.media.MediaDescriptionCompat;
39692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v4.media.MediaMetadataCompat;
40692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v4.media.session.MediaControllerCompat;
41692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v4.media.session.MediaSessionCompat;
42692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v4.media.session.PlaybackStateCompat;
43692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v4.util.ObjectsCompat;
44692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v4.view.accessibility.AccessibilityEventCompat;
45692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.support.v7.graphics.Palette;
46692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.text.TextUtils;
47692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.util.Log;
48d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Limimport android.view.ContextThemeWrapper;
49692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.KeyEvent;
50692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.LayoutInflater;
51692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.View;
52692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.View.MeasureSpec;
53692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.ViewGroup;
54692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.ViewTreeObserver;
55692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.accessibility.AccessibilityEvent;
56692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.accessibility.AccessibilityManager;
57692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.AccelerateDecelerateInterpolator;
58692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.AlphaAnimation;
59692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.Animation;
60692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.AnimationSet;
61692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.AnimationUtils;
62692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.Interpolator;
63692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.Transformation;
64692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.view.animation.TranslateAnimation;
65692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.ArrayAdapter;
66692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.Button;
67692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.FrameLayout;
68692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.ImageButton;
69692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.ImageView;
70692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.LinearLayout;
71692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.RelativeLayout;
72692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.SeekBar;
73692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport android.widget.TextView;
74692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
75d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Limimport com.android.media.update.ApiHelper;
76692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport com.android.media.update.R;
77692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport com.android.support.mediarouter.media.MediaRouteSelector;
78692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport com.android.support.mediarouter.media.MediaRouter;
79692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport com.android.support.mediarouter.app.OverlayListView.OverlayObject;
80692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
81692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.io.BufferedInputStream;
82692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.io.IOException;
83692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.io.InputStream;
84692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.net.URL;
85692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.net.URLConnection;
86692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.ArrayList;
87692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.HashMap;
88692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.HashSet;
89692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.List;
90692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.Map;
91692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.Set;
92692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limimport java.util.concurrent.TimeUnit;
93692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
94692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim/**
95692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * This class implements the route controller dialog for {@link MediaRouter}.
96692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * <p>
97692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * This dialog allows the user to control or disconnect from the currently selected route.
98692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * </p>
99692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim *
100692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * @see MediaRouteButton
101692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim * @see MediaRouteActionProvider
102692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim */
103692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Limpublic class MediaRouteControllerDialog extends AlertDialog {
104692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    // Tags should be less than 24 characters long (see docs for android.util.Log.isLoggable())
105692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    static final String TAG = "MediaRouteCtrlDialog";
106692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
107692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
108692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    // Time to wait before updating the volume when the user lets go of the seek bar
109692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    // to allow the route provider time to propagate the change and publish a new
110692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    // route descriptor.
111692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    static final int VOLUME_UPDATE_DELAY_MILLIS = 500;
112692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    static final int CONNECTION_TIMEOUT_MILLIS = (int) TimeUnit.SECONDS.toMillis(30L);
113692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
114692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private static final int BUTTON_NEUTRAL_RES_ID = android.R.id.button3;
115692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    static final int BUTTON_DISCONNECT_RES_ID = android.R.id.button2;
116692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    static final int BUTTON_STOP_RES_ID = android.R.id.button1;
117692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
118692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    final MediaRouter mRouter;
119692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private final MediaRouterCallback mCallback;
120692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    final MediaRouter.RouteInfo mRoute;
121692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
122692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Context mContext;
123692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean mCreated;
124692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean mAttachedToWindow;
125692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
126692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private int mDialogContentWidth;
127692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
128692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private View mCustomControlView;
129692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
130692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private Button mDisconnectButton;
131692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private Button mStopCastingButton;
132692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private ImageButton mPlaybackControlButton;
133692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private ImageButton mCloseButton;
134692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private MediaRouteExpandCollapseButton mGroupExpandCollapseButton;
135692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
136692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private FrameLayout mExpandableAreaLayout;
137692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private LinearLayout mDialogAreaLayout;
138692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    FrameLayout mDefaultControlLayout;
139692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private FrameLayout mCustomControlLayout;
140692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private ImageView mArtView;
141692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private TextView mTitleView;
142692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private TextView mSubtitleView;
143692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private TextView mRouteNameTextView;
144692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
145692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean mVolumeControlEnabled = true;
146692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    // Layout for media controllers including play/pause button and the main volume slider.
147692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private LinearLayout mMediaMainControlLayout;
148692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private RelativeLayout mPlaybackControlLayout;
149692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private LinearLayout mVolumeControlLayout;
150692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private View mDividerView;
151692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
152692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    OverlayListView mVolumeGroupList;
153692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    VolumeGroupAdapter mVolumeGroupAdapter;
154692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private List<MediaRouter.RouteInfo> mGroupMemberRoutes;
155692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Set<MediaRouter.RouteInfo> mGroupMemberRoutesAdded;
156692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private Set<MediaRouter.RouteInfo> mGroupMemberRoutesRemoved;
157692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Set<MediaRouter.RouteInfo> mGroupMemberRoutesAnimatingWithBitmap;
158692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    SeekBar mVolumeSlider;
159692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    VolumeChangeListener mVolumeChangeListener;
160692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    MediaRouter.RouteInfo mRouteInVolumeSliderTouched;
161692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private int mVolumeGroupListItemIconSize;
162692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private int mVolumeGroupListItemHeight;
163692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private int mVolumeGroupListMaxHeight;
164692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private final int mVolumeGroupListPaddingTop;
165692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Map<MediaRouter.RouteInfo, SeekBar> mVolumeSliderMap;
166692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
167692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    MediaControllerCompat mMediaController;
168692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    MediaControllerCallback mControllerCallback;
169692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    PlaybackStateCompat mState;
170692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    MediaDescriptionCompat mDescription;
171692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
172692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    FetchArtTask mFetchArtTask;
173692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Bitmap mArtIconBitmap;
174692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Uri mArtIconUri;
175692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    boolean mArtIconIsLoaded;
176692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Bitmap mArtIconLoadedBitmap;
177692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    int mArtIconBackgroundColor;
178692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
179692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    boolean mHasPendingUpdate;
180692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    boolean mPendingUpdateAnimationNeeded;
181692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
182692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    boolean mIsGroupExpanded;
183692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    boolean mIsGroupListAnimating;
184692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    boolean mIsGroupListAnimationPending;
185692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    int mGroupListAnimationDurationMs;
186692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private int mGroupListFadeInDurationMs;
187692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private int mGroupListFadeOutDurationMs;
188692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
189692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private Interpolator mInterpolator;
190692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private Interpolator mLinearOutSlowInInterpolator;
191692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private Interpolator mFastOutSlowInInterpolator;
192692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private Interpolator mAccelerateDecelerateInterpolator;
193692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
194692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    final AccessibilityManager mAccessibilityManager;
195692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
196692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    Runnable mGroupListFadeInAnimation = new Runnable() {
197692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
198692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void run() {
199692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            startGroupListFadeInAnimation();
200692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
201692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    };
202692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
203692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public MediaRouteControllerDialog(Context context) {
204692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        this(context, 0);
205692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
206692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
207692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public MediaRouteControllerDialog(Context context, int theme) {
208d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim        // TODO (b/72975976): Avoid to use ContextThemeWrapper with app context and lib theme.
20992fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten        super(new ContextThemeWrapper(context, ApiHelper.getLibTheme(context,
21092fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                MediaRouterThemeHelper.getRouterThemeId(context))), theme);
211692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mContext = getContext();
212692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
213692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mControllerCallback = new MediaControllerCallback();
214692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mRouter = MediaRouter.getInstance(mContext);
215692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mCallback = new MediaRouterCallback();
216692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mRoute = mRouter.getSelectedRoute();
217692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        setMediaSession(mRouter.getMediaSessionToken());
21892fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten        mVolumeGroupListPaddingTop = ApiHelper.getLibResources(context).getDimensionPixelSize(
219692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                R.dimen.mr_controller_volume_group_list_padding_top);
220692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mAccessibilityManager =
221692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
222d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim        mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
223d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim                mContext, android.R.interpolator.linear_out_slow_in);
224d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(
225d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim                mContext, android.R.interpolator.fast_out_slow_in);
226692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mAccelerateDecelerateInterpolator = new AccelerateDecelerateInterpolator();
227692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
228692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
229692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
230692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Gets the route that this dialog is controlling.
231692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
232692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public MediaRouter.RouteInfo getRoute() {
233692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mRoute;
234692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
235692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
236692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private MediaRouter.RouteGroup getGroup() {
237692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mRoute instanceof MediaRouter.RouteGroup) {
238692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return (MediaRouter.RouteGroup) mRoute;
239692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
240692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return null;
241692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
242692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
243692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
244692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Provides the subclass an opportunity to create a view that will replace the default media
245692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * controls for the currently playing content.
246692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     *
247692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @param savedInstanceState The dialog's saved instance state.
248692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @return The media control view, or null if none.
249692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
250692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public View onCreateMediaControlView(Bundle savedInstanceState) {
251692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return null;
252692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
253692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
254692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
255692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Gets the media control view that was created by {@link #onCreateMediaControlView(Bundle)}.
256692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     *
257692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @return The media control view, or null if none.
258692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
259692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public View getMediaControlView() {
260692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mCustomControlView;
261692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
262692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
263692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
264692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Sets whether to enable the volume slider and volume control using the volume keys
265692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * when the route supports it.
266692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * <p>
267692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * The default value is true.
268692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * </p>
269692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
270692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public void setVolumeControlEnabled(boolean enable) {
271692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mVolumeControlEnabled != enable) {
272692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mVolumeControlEnabled = enable;
273692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mCreated) {
274692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                update(false);
275692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
276692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
277692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
278692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
279692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
280692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Returns whether to enable the volume slider and volume control using the volume keys
281692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * when the route supports it.
282692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
283692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public boolean isVolumeControlEnabled() {
284692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mVolumeControlEnabled;
285692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
286692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
287692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
288692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Set the session to use for metadata and transport controls. The dialog
289692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * will listen to changes on this session and update the UI automatically in
290692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * response to changes.
291692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     *
292692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @param sessionToken The token for the session to use.
293692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
294692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void setMediaSession(MediaSessionCompat.Token sessionToken) {
295692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mMediaController != null) {
296692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mMediaController.unregisterCallback(mControllerCallback);
297692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mMediaController = null;
298692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
299692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (sessionToken == null) {
300692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return;
301692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
302692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (!mAttachedToWindow) {
303692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return;
304692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
305692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        try {
306692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mMediaController = new MediaControllerCompat(mContext, sessionToken);
307692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } catch (RemoteException e) {
308692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Log.e(TAG, "Error creating media controller in setMediaSession.", e);
309692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
310692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mMediaController != null) {
311692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mMediaController.registerCallback(mControllerCallback);
312692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
313692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        MediaMetadataCompat metadata = mMediaController == null ? null
314692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                : mMediaController.getMetadata();
315692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDescription = metadata == null ? null : metadata.getDescription();
316692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mState = mMediaController == null ? null : mMediaController.getPlaybackState();
317692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updateArtIconIfNeeded();
318692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        update(false);
319692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
320692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
321692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
322692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Gets the session to use for metadata and transport controls.
323692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     *
324692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * @return The token for the session to use or null if none.
325692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
326692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public MediaSessionCompat.Token getMediaSession() {
327692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mMediaController == null ? null : mMediaController.getSessionToken();
328692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
329692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
330692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    @Override
331692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    protected void onCreate(Bundle savedInstanceState) {
332692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        super.onCreate(savedInstanceState);
333692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
334692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        getWindow().setBackgroundDrawableResource(android.R.color.transparent);
335d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim
336d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim        setContentView(ApiHelper.inflateLibLayout(mContext,
33792fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                ApiHelper.getLibTheme(mContext, MediaRouterThemeHelper.getRouterThemeId(mContext)),
338d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim                R.layout.mr_controller_material_dialog_b));
339692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
340692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Remove the neutral button.
341692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        findViewById(BUTTON_NEUTRAL_RES_ID).setVisibility(View.GONE);
342692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
343692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ClickListener listener = new ClickListener();
344692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
345692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mExpandableAreaLayout = findViewById(R.id.mr_expandable_area);
346692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mExpandableAreaLayout.setOnClickListener(new View.OnClickListener() {
347692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
348692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onClick(View v) {
349692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                dismiss();
350692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
351692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        });
352692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDialogAreaLayout = findViewById(R.id.mr_dialog_area);
353692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDialogAreaLayout.setOnClickListener(new View.OnClickListener() {
354692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
355692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onClick(View v) {
356692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // Eat unhandled touch events.
357692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
358692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        });
359692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int color = MediaRouterThemeHelper.getButtonTextColor(mContext);
360692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDisconnectButton = findViewById(BUTTON_DISCONNECT_RES_ID);
361d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim        mDisconnectButton.setText(
36292fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                ApiHelper.getLibResources(mContext).getString(R.string.mr_controller_disconnect));
363692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDisconnectButton.setTextColor(color);
364692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDisconnectButton.setOnClickListener(listener);
365692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
366692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mStopCastingButton = findViewById(BUTTON_STOP_RES_ID);
367d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim        mStopCastingButton.setText(
36892fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                ApiHelper.getLibResources(mContext).getString(R.string.mr_controller_stop_casting));
369692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mStopCastingButton.setTextColor(color);
370692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mStopCastingButton.setOnClickListener(listener);
371692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
372692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mRouteNameTextView = findViewById(R.id.mr_name);
373692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mCloseButton = findViewById(R.id.mr_close);
374692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mCloseButton.setOnClickListener(listener);
375692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mCustomControlLayout = findViewById(R.id.mr_custom_control);
376692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDefaultControlLayout = findViewById(R.id.mr_default_control);
377692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
378692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Start the session activity when a content item (album art, title or subtitle) is clicked.
379692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        View.OnClickListener onClickListener = new View.OnClickListener() {
380692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
381692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onClick(View v) {
382692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (mMediaController != null) {
383692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    PendingIntent pi = mMediaController.getSessionActivity();
384692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (pi != null) {
385692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        try {
386692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            pi.send();
387692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            dismiss();
388692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        } catch (PendingIntent.CanceledException e) {
389692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            Log.e(TAG, pi + " was not sent, it had been canceled.");
390692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        }
391692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
392692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
393692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
394692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        };
395692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mArtView = findViewById(R.id.mr_art);
396692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mArtView.setOnClickListener(onClickListener);
397692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        findViewById(R.id.mr_control_title_container).setOnClickListener(onClickListener);
398692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
399692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mMediaMainControlLayout = findViewById(R.id.mr_media_main_control);
400692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDividerView = findViewById(R.id.mr_control_divider);
401692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
402692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mPlaybackControlLayout = findViewById(R.id.mr_playback_control);
403692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mTitleView = findViewById(R.id.mr_control_title);
404692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mSubtitleView = findViewById(R.id.mr_control_subtitle);
405692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mPlaybackControlButton = findViewById(R.id.mr_control_playback_ctrl);
406692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mPlaybackControlButton.setOnClickListener(listener);
407692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
408692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeControlLayout = findViewById(R.id.mr_volume_control);
409692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeControlLayout.setVisibility(View.GONE);
410692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeSlider = findViewById(R.id.mr_volume_slider);
411692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeSlider.setTag(mRoute);
412692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeChangeListener = new VolumeChangeListener();
413692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
414692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
415692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList = findViewById(R.id.mr_volume_group_list);
416692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mGroupMemberRoutes = new ArrayList<MediaRouter.RouteInfo>();
417692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupAdapter = new VolumeGroupAdapter(mVolumeGroupList.getContext(),
418692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mGroupMemberRoutes);
419692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList.setAdapter(mVolumeGroupAdapter);
420692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mGroupMemberRoutesAnimatingWithBitmap = new HashSet<>();
421692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
422692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        MediaRouterThemeHelper.setMediaControlsBackgroundColor(mContext,
423692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mMediaMainControlLayout, mVolumeGroupList, getGroup() != null);
424692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        MediaRouterThemeHelper.setVolumeSliderColor(mContext,
425692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                (MediaRouteVolumeSlider) mVolumeSlider, mMediaMainControlLayout);
426692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeSliderMap = new HashMap<>();
427692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeSliderMap.put(mRoute, mVolumeSlider);
428692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
429692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mGroupExpandCollapseButton =
430692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                findViewById(R.id.mr_group_expand_collapse);
431692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() {
432692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
433692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onClick(View v) {
434692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mIsGroupExpanded = !mIsGroupExpanded;
435692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (mIsGroupExpanded) {
436692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mVolumeGroupList.setVisibility(View.VISIBLE);
437692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
438692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                loadInterpolator();
439692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                updateLayoutHeight(true);
440692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
441692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        });
442692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        loadInterpolator();
44392fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten        mGroupListAnimationDurationMs = ApiHelper.getLibResources(mContext).getInteger(
444692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                R.integer.mr_controller_volume_group_list_animation_duration_ms);
44592fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten        mGroupListFadeInDurationMs = ApiHelper.getLibResources(mContext).getInteger(
446692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                R.integer.mr_controller_volume_group_list_fade_in_duration_ms);
44792fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten        mGroupListFadeOutDurationMs = ApiHelper.getLibResources(mContext).getInteger(
448692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                R.integer.mr_controller_volume_group_list_fade_out_duration_ms);
449692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
450692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mCustomControlView = onCreateMediaControlView(savedInstanceState);
451692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mCustomControlView != null) {
452692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mCustomControlLayout.addView(mCustomControlView);
453692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mCustomControlLayout.setVisibility(View.VISIBLE);
454692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
455692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mCreated = true;
456692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updateLayout();
457692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
458692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
459692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
460692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Sets the width of the dialog. Also called when configuration changes.
461692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
462692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void updateLayout() {
46392fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten        int width = MediaRouteDialogHelper.getDialogWidth(mContext);
464692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        getWindow().setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT);
465692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
466692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        View decorView = getWindow().getDecorView();
467692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDialogContentWidth = width - decorView.getPaddingLeft() - decorView.getPaddingRight();
468692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
46992fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten        Resources res = ApiHelper.getLibResources(mContext);
470692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupListItemIconSize = res.getDimensionPixelSize(
471692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                R.dimen.mr_controller_volume_group_list_item_icon_size);
472692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupListItemHeight = res.getDimensionPixelSize(
473692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                R.dimen.mr_controller_volume_group_list_item_height);
474692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupListMaxHeight = res.getDimensionPixelSize(
475692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                R.dimen.mr_controller_volume_group_list_max_height);
476692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
477692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Fetch art icons again for layout changes to resize it accordingly
478692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mArtIconBitmap = null;
479692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mArtIconUri = null;
480692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updateArtIconIfNeeded();
481692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        update(false);
482692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
483692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
484692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    @Override
485692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public void onAttachedToWindow() {
486692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        super.onAttachedToWindow();
487692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mAttachedToWindow = true;
488692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
489692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mRouter.addCallback(MediaRouteSelector.EMPTY, mCallback,
490692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                MediaRouter.CALLBACK_FLAG_UNFILTERED_EVENTS);
491692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        setMediaSession(mRouter.getMediaSessionToken());
492692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
493692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
494692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    @Override
495692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public void onDetachedFromWindow() {
496692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mRouter.removeCallback(mCallback);
497692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        setMediaSession(null);
498692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mAttachedToWindow = false;
499692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        super.onDetachedFromWindow();
500692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
501692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
502692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    @Override
503692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public boolean onKeyDown(int keyCode, KeyEvent event) {
504692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
505692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
506692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mRoute.requestUpdateVolume(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ? -1 : 1);
507692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return true;
508692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
509692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return super.onKeyDown(keyCode, event);
510692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
511692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
512692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    @Override
513692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    public boolean onKeyUp(int keyCode, KeyEvent event) {
514692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
515692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                || keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
516692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return true;
517692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
518692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return super.onKeyUp(keyCode, event);
519692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
520692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
521692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void update(boolean animate) {
522692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Defer dialog updates if a user is adjusting a volume in the list
523692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mRouteInVolumeSliderTouched != null) {
524692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mHasPendingUpdate = true;
525692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mPendingUpdateAnimationNeeded |= animate;
526692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return;
527692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
528692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mHasPendingUpdate = false;
529692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mPendingUpdateAnimationNeeded = false;
530692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (!mRoute.isSelected() || mRoute.isDefaultOrBluetooth()) {
531692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            dismiss();
532692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return;
533692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
534692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (!mCreated) {
535692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return;
536692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
537692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
538692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mRouteNameTextView.setText(mRoute.getName());
539692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE);
540692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mCustomControlView == null && mArtIconIsLoaded) {
541692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (isBitmapRecycled(mArtIconLoadedBitmap)) {
542692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Log.w(TAG, "Can't set artwork image with recycled bitmap: " + mArtIconLoadedBitmap);
543692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
544692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtView.setImageBitmap(mArtIconLoadedBitmap);
545692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtView.setBackgroundColor(mArtIconBackgroundColor);
546692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
547692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            clearLoadedBitmap();
548692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
549692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updateVolumeControlLayout();
550692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updatePlaybackControlLayout();
551692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updateLayoutHeight(animate);
552692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
553692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
554692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean isBitmapRecycled(Bitmap bitmap) {
555692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return bitmap != null && bitmap.isRecycled();
556692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
557692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
558692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean canShowPlaybackControlLayout() {
559692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mCustomControlView == null && (mDescription != null || mState != null);
560692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
561692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
562692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
563692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Returns the height of main media controller which includes playback control and master
564692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * volume control.
565692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
566692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private int getMainControllerHeight(boolean showPlaybackControl) {
567692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int height = 0;
568692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (showPlaybackControl || mVolumeControlLayout.getVisibility() == View.VISIBLE) {
569692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            height += mMediaMainControlLayout.getPaddingTop()
570692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    + mMediaMainControlLayout.getPaddingBottom();
571692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (showPlaybackControl) {
572692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                height +=  mPlaybackControlLayout.getMeasuredHeight();
573692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
574692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mVolumeControlLayout.getVisibility() == View.VISIBLE) {
575692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                height += mVolumeControlLayout.getMeasuredHeight();
576692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
577692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (showPlaybackControl && mVolumeControlLayout.getVisibility() == View.VISIBLE) {
578692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                height += mDividerView.getMeasuredHeight();
579692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
580692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
581692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return height;
582692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
583692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
584692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void updateMediaControlVisibility(boolean canShowPlaybackControlLayout) {
585692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // TODO: Update the top and bottom padding of the control layout according to the display
586692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // height.
587692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDividerView.setVisibility((mVolumeControlLayout.getVisibility() == View.VISIBLE
588692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                && canShowPlaybackControlLayout) ? View.VISIBLE : View.GONE);
589692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mMediaMainControlLayout.setVisibility((mVolumeControlLayout.getVisibility() == View.GONE
590692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                && !canShowPlaybackControlLayout) ? View.GONE : View.VISIBLE);
591692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
592692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
593692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void updateLayoutHeight(final boolean animate) {
594692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // We need to defer the update until the first layout has occurred, as we don't yet know the
595692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // overall visible display size in which the window this view is attached to has been
596692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // positioned in.
597692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDefaultControlLayout.requestLayout();
598692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ViewTreeObserver observer = mDefaultControlLayout.getViewTreeObserver();
599692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
600692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
601692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onGlobalLayout() {
602692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mDefaultControlLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
603692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (mIsGroupListAnimating) {
604692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mIsGroupListAnimationPending = true;
605692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                } else {
606692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    updateLayoutHeightInternal(animate);
607692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
608692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
609692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        });
610692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
611692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
612692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
613692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Updates the height of views and hide artwork or metadata if space is limited.
614692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
615692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void updateLayoutHeightInternal(boolean animate) {
616692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Measure the size of widgets and get the height of main components.
617692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int oldHeight = getLayoutHeight(mMediaMainControlLayout);
618692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        setLayoutHeight(mMediaMainControlLayout, ViewGroup.LayoutParams.MATCH_PARENT);
619692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updateMediaControlVisibility(canShowPlaybackControlLayout());
620692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        View decorView = getWindow().getDecorView();
621692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        decorView.measure(
622692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                MeasureSpec.makeMeasureSpec(getWindow().getAttributes().width, MeasureSpec.EXACTLY),
623692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                MeasureSpec.UNSPECIFIED);
624692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        setLayoutHeight(mMediaMainControlLayout, oldHeight);
625692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int artViewHeight = 0;
626692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mCustomControlView == null && mArtView.getDrawable() instanceof BitmapDrawable) {
627692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Bitmap art = ((BitmapDrawable) mArtView.getDrawable()).getBitmap();
628692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (art != null) {
629692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                artViewHeight = getDesiredArtHeight(art.getWidth(), art.getHeight());
630692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtView.setScaleType(art.getWidth() >= art.getHeight()
631692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        ? ImageView.ScaleType.FIT_XY : ImageView.ScaleType.FIT_CENTER);
632692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
633692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
634692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int mainControllerHeight = getMainControllerHeight(canShowPlaybackControlLayout());
635692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int volumeGroupListCount = mGroupMemberRoutes.size();
636692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Scale down volume group list items in landscape mode.
637692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int expandedGroupListHeight = getGroup() == null ? 0 :
638692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeGroupListItemHeight * getGroup().getRoutes().size();
639692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (volumeGroupListCount > 0) {
640692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            expandedGroupListHeight += mVolumeGroupListPaddingTop;
641692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
642692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        expandedGroupListHeight = Math.min(expandedGroupListHeight, mVolumeGroupListMaxHeight);
643692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int visibleGroupListHeight = mIsGroupExpanded ? expandedGroupListHeight : 0;
644692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
645692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int desiredControlLayoutHeight =
646692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Math.max(artViewHeight, visibleGroupListHeight) + mainControllerHeight;
647692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Rect visibleRect = new Rect();
648692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        decorView.getWindowVisibleDisplayFrame(visibleRect);
649692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Height of non-control views in decor view.
650692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // This includes title bar, button bar, and dialog's vertical padding which should be
651692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // always shown.
652692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int nonControlViewHeight = mDialogAreaLayout.getMeasuredHeight()
653692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                - mDefaultControlLayout.getMeasuredHeight();
654692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Maximum allowed height for controls to fit screen.
655692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int maximumControlViewHeight = visibleRect.height() - nonControlViewHeight;
656692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
657692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Show artwork if it fits the screen.
658692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mCustomControlView == null && artViewHeight > 0
659692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                && desiredControlLayoutHeight <= maximumControlViewHeight) {
660692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mArtView.setVisibility(View.VISIBLE);
661692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            setLayoutHeight(mArtView, artViewHeight);
662692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else {
663692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (getLayoutHeight(mVolumeGroupList) + mMediaMainControlLayout.getMeasuredHeight()
664692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    >= mDefaultControlLayout.getMeasuredHeight()) {
665692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtView.setVisibility(View.GONE);
666692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
667692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            artViewHeight = 0;
668692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            desiredControlLayoutHeight = visibleGroupListHeight + mainControllerHeight;
669692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
670692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Show the playback control if it fits the screen.
671692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (canShowPlaybackControlLayout()
672692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                && desiredControlLayoutHeight <= maximumControlViewHeight) {
673692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mPlaybackControlLayout.setVisibility(View.VISIBLE);
674692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else {
675692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mPlaybackControlLayout.setVisibility(View.GONE);
676692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
677692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        updateMediaControlVisibility(mPlaybackControlLayout.getVisibility() == View.VISIBLE);
678692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mainControllerHeight = getMainControllerHeight(
679692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mPlaybackControlLayout.getVisibility() == View.VISIBLE);
680692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        desiredControlLayoutHeight =
681692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Math.max(artViewHeight, visibleGroupListHeight) + mainControllerHeight;
682692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
683692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Limit the volume group list height to fit the screen.
684692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (desiredControlLayoutHeight > maximumControlViewHeight) {
685692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            visibleGroupListHeight -= (desiredControlLayoutHeight - maximumControlViewHeight);
686692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            desiredControlLayoutHeight = maximumControlViewHeight;
687692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
688692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Update the layouts with the computed heights.
689692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mMediaMainControlLayout.clearAnimation();
690692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList.clearAnimation();
691692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mDefaultControlLayout.clearAnimation();
692692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (animate) {
693692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animateLayoutHeight(mMediaMainControlLayout, mainControllerHeight);
694692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animateLayoutHeight(mVolumeGroupList, visibleGroupListHeight);
695692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animateLayoutHeight(mDefaultControlLayout, desiredControlLayoutHeight);
696692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else {
697692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            setLayoutHeight(mMediaMainControlLayout, mainControllerHeight);
698692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            setLayoutHeight(mVolumeGroupList, visibleGroupListHeight);
699692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            setLayoutHeight(mDefaultControlLayout, desiredControlLayoutHeight);
700692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
701692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Maximize the window size with a transparent layout in advance for smooth animation.
702692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        setLayoutHeight(mExpandableAreaLayout, visibleRect.height());
703692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        rebuildVolumeGroupList(animate);
704692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
705692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
706692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void updateVolumeGroupItemHeight(View item) {
707692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        LinearLayout container = (LinearLayout) item.findViewById(R.id.volume_item_container);
708692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        setLayoutHeight(container, mVolumeGroupListItemHeight);
709692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        View icon = item.findViewById(R.id.mr_volume_item_icon);
710692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ViewGroup.LayoutParams lp = icon.getLayoutParams();
711692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        lp.width = mVolumeGroupListItemIconSize;
712692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        lp.height = mVolumeGroupListItemIconSize;
713692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        icon.setLayoutParams(lp);
714692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
715692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
716692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void animateLayoutHeight(final View view, int targetHeight) {
717692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        final int startValue = getLayoutHeight(view);
718692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        final int endValue = targetHeight;
719692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Animation anim = new Animation() {
720692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
721692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            protected void applyTransformation(float interpolatedTime, Transformation t) {
722692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                int height = startValue - (int) ((startValue - endValue) * interpolatedTime);
723692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                setLayoutHeight(view, height);
724692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
725692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        };
726692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        anim.setDuration(mGroupListAnimationDurationMs);
727692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (android.os.Build.VERSION.SDK_INT >= 21) {
728692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            anim.setInterpolator(mInterpolator);
729692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
730692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        view.startAnimation(anim);
731692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
732692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
733692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void loadInterpolator() {
734d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim        mInterpolator =
735d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim                mIsGroupExpanded ? mLinearOutSlowInInterpolator : mFastOutSlowInInterpolator;
736692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
737692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
738692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void updateVolumeControlLayout() {
739692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (isVolumeControlAvailable(mRoute)) {
740692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mVolumeControlLayout.getVisibility() == View.GONE) {
741692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeControlLayout.setVisibility(View.VISIBLE);
742692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeSlider.setMax(mRoute.getVolumeMax());
743692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeSlider.setProgress(mRoute.getVolume());
744692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mGroupExpandCollapseButton.setVisibility(getGroup() == null ? View.GONE
745692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        : View.VISIBLE);
746692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
747692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else {
748692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mVolumeControlLayout.setVisibility(View.GONE);
749692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
750692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
751692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
752692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void rebuildVolumeGroupList(boolean animate) {
753692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        List<MediaRouter.RouteInfo> routes = getGroup() == null ? null : getGroup().getRoutes();
754692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (routes == null) {
755692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mGroupMemberRoutes.clear();
756692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mVolumeGroupAdapter.notifyDataSetChanged();
757692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else if (MediaRouteDialogHelper.listUnorderedEquals(mGroupMemberRoutes, routes)) {
758692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mVolumeGroupAdapter.notifyDataSetChanged();
759692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else {
760692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            HashMap<MediaRouter.RouteInfo, Rect> previousRouteBoundMap = animate
761692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    ? MediaRouteDialogHelper.getItemBoundMap(mVolumeGroupList, mVolumeGroupAdapter)
762692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    : null;
763692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            HashMap<MediaRouter.RouteInfo, BitmapDrawable> previousRouteBitmapMap = animate
764692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    ? MediaRouteDialogHelper.getItemBitmapMap(mContext, mVolumeGroupList,
765692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            mVolumeGroupAdapter) : null;
766692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mGroupMemberRoutesAdded =
767692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    MediaRouteDialogHelper.getItemsAdded(mGroupMemberRoutes, routes);
768692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mGroupMemberRoutesRemoved = MediaRouteDialogHelper.getItemsRemoved(mGroupMemberRoutes,
769692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    routes);
770692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mGroupMemberRoutes.addAll(0, mGroupMemberRoutesAdded);
771692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mGroupMemberRoutes.removeAll(mGroupMemberRoutesRemoved);
772692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mVolumeGroupAdapter.notifyDataSetChanged();
773692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (animate && mIsGroupExpanded
774692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    && mGroupMemberRoutesAdded.size() + mGroupMemberRoutesRemoved.size() > 0) {
775692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                animateGroupListItems(previousRouteBoundMap, previousRouteBitmapMap);
776692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
777692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mGroupMemberRoutesAdded = null;
778692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mGroupMemberRoutesRemoved = null;
779692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
780692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
781692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
782692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
783692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void animateGroupListItems(final Map<MediaRouter.RouteInfo, Rect> previousRouteBoundMap,
784692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            final Map<MediaRouter.RouteInfo, BitmapDrawable> previousRouteBitmapMap) {
785692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList.setEnabled(false);
786692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList.requestLayout();
787692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mIsGroupListAnimating = true;
788692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ViewTreeObserver observer = mVolumeGroupList.getViewTreeObserver();
789692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
790692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
791692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onGlobalLayout() {
792692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeGroupList.getViewTreeObserver().removeGlobalOnLayoutListener(this);
793692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                animateGroupListItemsInternal(previousRouteBoundMap, previousRouteBitmapMap);
794692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
795692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        });
796692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
797692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
798692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void animateGroupListItemsInternal(
799692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Map<MediaRouter.RouteInfo, Rect> previousRouteBoundMap,
800692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Map<MediaRouter.RouteInfo, BitmapDrawable> previousRouteBitmapMap) {
801692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mGroupMemberRoutesAdded == null || mGroupMemberRoutesRemoved == null) {
802692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return;
803692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
804692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int groupSizeDelta = mGroupMemberRoutesAdded.size() - mGroupMemberRoutesRemoved.size();
805692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        boolean listenerRegistered = false;
806692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Animation.AnimationListener listener = new Animation.AnimationListener() {
807692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
808692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onAnimationStart(Animation animation) {
809692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeGroupList.startAnimationAll();
810692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeGroupList.postDelayed(mGroupListFadeInAnimation,
811692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        mGroupListAnimationDurationMs);
812692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
813692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
814692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
815692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onAnimationEnd(Animation animation) { }
816692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
817692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
818692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onAnimationRepeat(Animation animation) { }
819692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        };
820692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
821692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Animate visible items from previous positions to current positions except routes added
822692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // just before. Added routes will remain hidden until translate animation finishes.
823692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int first = mVolumeGroupList.getFirstVisiblePosition();
824692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
825692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            View view = mVolumeGroupList.getChildAt(i);
826692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            int position = first + i;
827692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            MediaRouter.RouteInfo route = mVolumeGroupAdapter.getItem(position);
828692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Rect previousBounds = previousRouteBoundMap.get(route);
829692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            int currentTop = view.getTop();
830692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            int previousTop = previousBounds != null ? previousBounds.top
831692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    : (currentTop + mVolumeGroupListItemHeight * groupSizeDelta);
832692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            AnimationSet animSet = new AnimationSet(true);
833692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mGroupMemberRoutesAdded != null && mGroupMemberRoutesAdded.contains(route)) {
834692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                previousTop = currentTop;
835692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Animation alphaAnim = new AlphaAnimation(0.0f, 0.0f);
836692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                alphaAnim.setDuration(mGroupListFadeInDurationMs);
837692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                animSet.addAnimation(alphaAnim);
838692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
839692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Animation translationAnim = new TranslateAnimation(0, 0, previousTop - currentTop, 0);
840692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            translationAnim.setDuration(mGroupListAnimationDurationMs);
841692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animSet.addAnimation(translationAnim);
842692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animSet.setFillAfter(true);
843692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animSet.setFillEnabled(true);
844692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animSet.setInterpolator(mInterpolator);
845692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (!listenerRegistered) {
846692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                listenerRegistered = true;
847692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                animSet.setAnimationListener(listener);
848692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
849692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            view.clearAnimation();
850692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            view.startAnimation(animSet);
851692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            previousRouteBoundMap.remove(route);
852692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            previousRouteBitmapMap.remove(route);
853692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
854692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
855692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // If a member route doesn't exist any longer, it can be either removed or moved out of the
856692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // ListView layout boundary. In this case, use the previously captured bitmaps for
857692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // animation.
858692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        for (Map.Entry<MediaRouter.RouteInfo, BitmapDrawable> item
859692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                : previousRouteBitmapMap.entrySet()) {
860692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            final MediaRouter.RouteInfo route = item.getKey();
861692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            final BitmapDrawable bitmap = item.getValue();
862692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            final Rect bounds = previousRouteBoundMap.get(route);
863692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            OverlayObject object = null;
864692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mGroupMemberRoutesRemoved.contains(route)) {
865692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                object = new OverlayObject(bitmap, bounds).setAlphaAnimation(1.0f, 0.0f)
866692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        .setDuration(mGroupListFadeOutDurationMs)
867692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        .setInterpolator(mInterpolator);
868692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
869692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                int deltaY = groupSizeDelta * mVolumeGroupListItemHeight;
870692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                object = new OverlayObject(bitmap, bounds).setTranslateYAnimation(deltaY)
871692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        .setDuration(mGroupListAnimationDurationMs)
872692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        .setInterpolator(mInterpolator)
873692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        .setAnimationEndListener(new OverlayObject.OnAnimationEndListener() {
874692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            @Override
875692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            public void onAnimationEnd() {
876692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                                mGroupMemberRoutesAnimatingWithBitmap.remove(route);
877692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                                mVolumeGroupAdapter.notifyDataSetChanged();
878692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            }
879692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        });
880692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mGroupMemberRoutesAnimatingWithBitmap.add(route);
881692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
882692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mVolumeGroupList.addOverlayObject(object);
883692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
884692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
885692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
886692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void startGroupListFadeInAnimation() {
887692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        clearGroupListAnimation(true);
888692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList.requestLayout();
889692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ViewTreeObserver observer = mVolumeGroupList.getViewTreeObserver();
890692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
891692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
892692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onGlobalLayout() {
893692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeGroupList.getViewTreeObserver().removeGlobalOnLayoutListener(this);
894692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                startGroupListFadeInAnimationInternal();
895692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
896692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        });
897692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
898692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
899692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void startGroupListFadeInAnimationInternal() {
900692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mGroupMemberRoutesAdded != null && mGroupMemberRoutesAdded.size() != 0) {
901692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            fadeInAddedRoutes();
902692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else {
903692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            finishAnimation(true);
904692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
905692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
906692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
907692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void finishAnimation(boolean animate) {
908692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mGroupMemberRoutesAdded = null;
909692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mGroupMemberRoutesRemoved = null;
910692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mIsGroupListAnimating = false;
911692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mIsGroupListAnimationPending) {
912692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mIsGroupListAnimationPending = false;
913692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            updateLayoutHeight(animate);
914692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
915692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList.setEnabled(true);
916692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
917692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
918692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void fadeInAddedRoutes() {
919692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Animation.AnimationListener listener = new Animation.AnimationListener() {
920692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
921692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onAnimationStart(Animation animation) { }
922692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
923692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
924692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onAnimationEnd(Animation animation) {
925692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                finishAnimation(true);
926692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
927692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
928692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
929692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void onAnimationRepeat(Animation animation) { }
930692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        };
931692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        boolean listenerRegistered = false;
932692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int first = mVolumeGroupList.getFirstVisiblePosition();
933692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
934692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            View view = mVolumeGroupList.getChildAt(i);
935692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            int position = first + i;
936692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            MediaRouter.RouteInfo route = mVolumeGroupAdapter.getItem(position);
937692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mGroupMemberRoutesAdded.contains(route)) {
938692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Animation alphaAnim = new AlphaAnimation(0.0f, 1.0f);
939692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                alphaAnim.setDuration(mGroupListFadeInDurationMs);
940692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                alphaAnim.setFillEnabled(true);
941692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                alphaAnim.setFillAfter(true);
942692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (!listenerRegistered) {
943692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    listenerRegistered = true;
944692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    alphaAnim.setAnimationListener(listener);
945692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
946692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                view.clearAnimation();
947692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                view.startAnimation(alphaAnim);
948692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
949692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
950692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
951692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
952692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void clearGroupListAnimation(boolean exceptAddedRoutes) {
953692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        int first = mVolumeGroupList.getFirstVisiblePosition();
954692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        for (int i = 0; i < mVolumeGroupList.getChildCount(); ++i) {
955692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            View view = mVolumeGroupList.getChildAt(i);
956692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            int position = first + i;
957692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            MediaRouter.RouteInfo route = mVolumeGroupAdapter.getItem(position);
958692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (exceptAddedRoutes && mGroupMemberRoutesAdded != null
959692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    && mGroupMemberRoutesAdded.contains(route)) {
960692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                continue;
961692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
962692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            LinearLayout container = (LinearLayout) view.findViewById(R.id.volume_item_container);
963692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            container.setVisibility(View.VISIBLE);
964692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            AnimationSet animSet = new AnimationSet(true);
965692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Animation alphaAnim = new AlphaAnimation(1.0f, 1.0f);
966692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            alphaAnim.setDuration(0);
967692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animSet.addAnimation(alphaAnim);
968692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Animation translationAnim = new TranslateAnimation(0, 0, 0, 0);
969692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            translationAnim.setDuration(0);
970692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animSet.setFillAfter(true);
971692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            animSet.setFillEnabled(true);
972692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            view.clearAnimation();
973692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            view.startAnimation(animSet);
974692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
975692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mVolumeGroupList.stopAnimationAll();
976692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (!exceptAddedRoutes) {
977692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            finishAnimation(false);
978692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
979692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
980692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
981692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private void updatePlaybackControlLayout() {
982692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (canShowPlaybackControlLayout()) {
983692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            CharSequence title = mDescription == null ? null : mDescription.getTitle();
984692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            boolean hasTitle = !TextUtils.isEmpty(title);
985692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
986692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle();
987692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            boolean hasSubtitle = !TextUtils.isEmpty(subtitle);
988692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
989692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            boolean showTitle = false;
990692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            boolean showSubtitle = false;
991692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mRoute.getPresentationDisplayId()
992692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    != MediaRouter.RouteInfo.PRESENTATION_DISPLAY_ID_NONE) {
993692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // The user is currently casting screen.
99492fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                mTitleView.setText(ApiHelper.getLibResources(mContext).getString(
995d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim                        R.string.mr_controller_casting_screen));
996692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                showTitle = true;
997692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else if (mState == null || mState.getState() == PlaybackStateCompat.STATE_NONE) {
998692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // Show "No media selected" as we don't yet know the playback state.
99992fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                mTitleView.setText(ApiHelper.getLibResources(mContext).getString(
1000d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim                        R.string.mr_controller_no_media_selected));
1001692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                showTitle = true;
1002692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else if (!hasTitle && !hasSubtitle) {
100392fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                mTitleView.setText(ApiHelper.getLibResources(mContext).getString(
1004d5b1f00dbd91f5bc64f30891ec7a35f28274dbb0Sungsoo Lim                        R.string.mr_controller_no_info_available));
1005692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                showTitle = true;
1006692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
1007692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (hasTitle) {
1008692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mTitleView.setText(title);
1009692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    showTitle = true;
1010692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1011692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (hasSubtitle) {
1012692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mSubtitleView.setText(subtitle);
1013692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    showSubtitle = true;
1014692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1015692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1016692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mTitleView.setVisibility(showTitle ? View.VISIBLE : View.GONE);
1017692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mSubtitleView.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
1018692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1019692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mState != null) {
1020692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
1021692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
1022692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Context playbackControlButtonContext = mPlaybackControlButton.getContext();
1023692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                boolean visible = true;
1024692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                int iconDrawableAttr = 0;
1025692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                int iconDescResId = 0;
1026692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (isPlaying && isPauseActionSupported()) {
1027692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    iconDrawableAttr = R.attr.mediaRoutePauseDrawable;
1028692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    iconDescResId = R.string.mr_controller_pause;
1029692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                } else if (isPlaying && isStopActionSupported()) {
1030692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    iconDrawableAttr = R.attr.mediaRouteStopDrawable;
1031692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    iconDescResId = R.string.mr_controller_stop;
1032692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                } else if (!isPlaying && isPlayActionSupported()) {
1033692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    iconDrawableAttr = R.attr.mediaRoutePlayDrawable;
1034692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    iconDescResId = R.string.mr_controller_play;
1035692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                } else {
1036692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    visible = false;
1037692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1038692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mPlaybackControlButton.setVisibility(visible ? View.VISIBLE : View.GONE);
1039692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (visible) {
1040692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mPlaybackControlButton.setImageResource(
1041692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            MediaRouterThemeHelper.getThemeResource(
1042692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                                    playbackControlButtonContext, iconDrawableAttr));
1043692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mPlaybackControlButton.setContentDescription(
1044692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            playbackControlButtonContext.getResources()
1045692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                                    .getText(iconDescResId));
1046692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1047692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1048692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1049692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1050692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1051692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean isPlayActionSupported() {
1052692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return (mState.getActions() & (ACTION_PLAY | ACTION_PLAY_PAUSE)) != 0;
1053692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1054692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1055692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean isPauseActionSupported() {
1056692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return (mState.getActions() & (ACTION_PAUSE | ACTION_PLAY_PAUSE)) != 0;
1057692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1058692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1059692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean isStopActionSupported() {
1060692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return (mState.getActions() & ACTION_STOP) != 0;
1061692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1062692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1063692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    boolean isVolumeControlAvailable(MediaRouter.RouteInfo route) {
1064692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return mVolumeControlEnabled && route.getVolumeHandling()
1065692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                == MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE;
1066692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1067692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1068692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private static int getLayoutHeight(View view) {
1069692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return view.getLayoutParams().height;
1070692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1071692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1072692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    static void setLayoutHeight(View view, int height) {
1073692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ViewGroup.LayoutParams lp = view.getLayoutParams();
1074692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        lp.height = height;
1075692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        view.setLayoutParams(lp);
1076692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1077692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1078692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private static boolean uriEquals(Uri uri1, Uri uri2) {
1079692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (uri1 != null && uri1.equals(uri2)) {
1080692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return true;
1081692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else if (uri1 == null && uri2 == null) {
1082692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return true;
1083692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1084692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return false;
1085692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1086692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1087692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
1088692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Returns desired art height to fit into controller dialog.
1089692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
1090692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    int getDesiredArtHeight(int originalWidth, int originalHeight) {
1091692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (originalWidth >= originalHeight) {
1092692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            // For landscape art, fit width to dialog width.
1093692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return (int) ((float) mDialogContentWidth * originalHeight / originalWidth + 0.5f);
1094692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1095692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // For portrait art, fit height to 16:9 ratio case's height.
1096692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return (int) ((float) mDialogContentWidth * 9 / 16 + 0.5f);
1097692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1098692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1099692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void updateArtIconIfNeeded() {
1100692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mCustomControlView != null || !isIconChanged()) {
1101692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return;
1102692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1103692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (mFetchArtTask != null) {
1104692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mFetchArtTask.cancel(true);
1105692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1106692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mFetchArtTask = new FetchArtTask();
1107692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mFetchArtTask.execute();
1108692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1109692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1110692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
1111692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Clear the bitmap loaded by FetchArtTask. Will be called after the loaded bitmaps are applied
1112692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * to artwork, or no longer valid.
1113692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
1114692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    void clearLoadedBitmap() {
1115692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mArtIconIsLoaded = false;
1116692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mArtIconLoadedBitmap = null;
1117692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        mArtIconBackgroundColor = 0;
1118692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1119692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1120692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    /**
1121692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Returns whether a new art image is different from an original art image. Compares
1122692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * Bitmap objects first, and then compares URIs only if bitmap is unchanged with
1123692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     * a null value.
1124692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim     */
1125692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private boolean isIconChanged() {
1126692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Bitmap newBitmap = mDescription == null ? null : mDescription.getIconBitmap();
1127692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Uri newUri = mDescription == null ? null : mDescription.getIconUri();
1128692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Bitmap oldBitmap = mFetchArtTask == null ? mArtIconBitmap : mFetchArtTask.getIconBitmap();
1129692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        Uri oldUri = mFetchArtTask == null ? mArtIconUri : mFetchArtTask.getIconUri();
1130692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        if (oldBitmap != newBitmap) {
1131692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return true;
1132692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        } else if (oldBitmap == null && !uriEquals(oldUri, newUri)) {
1133692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return true;
1134692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1135692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        return false;
1136692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1137692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1138692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private final class MediaRouterCallback extends MediaRouter.Callback {
1139692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        MediaRouterCallback() {
1140692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1141692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1142692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1143692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
1144692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            update(false);
1145692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1146692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1147692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1148692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
1149692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            update(true);
1150692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1151692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1152692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1153692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
1154692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            SeekBar volumeSlider = mVolumeSliderMap.get(route);
1155692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            int volume = route.getVolume();
1156692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (DEBUG) {
1157692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Log.d(TAG, "onRouteVolumeChanged(), route.getVolume:" + volume);
1158692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1159692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (volumeSlider != null && mRouteInVolumeSliderTouched != route) {
1160692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                volumeSlider.setProgress(volume);
1161692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1162692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1163692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1164692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1165692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private final class MediaControllerCallback extends MediaControllerCompat.Callback {
1166692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        MediaControllerCallback() {
1167692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1168692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1169692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1170692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onSessionDestroyed() {
1171692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mMediaController != null) {
1172692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mMediaController.unregisterCallback(mControllerCallback);
1173692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mMediaController = null;
1174692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1175692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1176692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1177692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1178692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onPlaybackStateChanged(PlaybackStateCompat state) {
1179692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mState = state;
1180692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            update(false);
1181692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1182692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1183692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1184692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onMetadataChanged(MediaMetadataCompat metadata) {
1185692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mDescription = metadata == null ? null : metadata.getDescription();
1186692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            updateArtIconIfNeeded();
1187692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            update(false);
1188692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1189692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1190692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1191692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private final class ClickListener implements View.OnClickListener {
1192692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        ClickListener() {
1193692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1194692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1195692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1196692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onClick(View v) {
1197692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            int id = v.getId();
1198692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (id == BUTTON_STOP_RES_ID || id == BUTTON_DISCONNECT_RES_ID) {
1199692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (mRoute.isSelected()) {
1200692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mRouter.unselect(id == BUTTON_STOP_RES_ID ?
1201692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            MediaRouter.UNSELECT_REASON_STOPPED :
1202692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            MediaRouter.UNSELECT_REASON_DISCONNECTED);
1203692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1204692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                dismiss();
1205692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else if (id == R.id.mr_control_playback_ctrl) {
1206692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (mMediaController != null && mState != null) {
1207692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_PLAYING;
1208692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    int actionDescResId = 0;
1209692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (isPlaying && isPauseActionSupported()) {
1210692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        mMediaController.getTransportControls().pause();
1211692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        actionDescResId = R.string.mr_controller_pause;
1212692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    } else if (isPlaying && isStopActionSupported()) {
1213692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        mMediaController.getTransportControls().stop();
1214692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        actionDescResId = R.string.mr_controller_stop;
1215692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    } else if (!isPlaying && isPlayActionSupported()){
1216692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        mMediaController.getTransportControls().play();
1217692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        actionDescResId = R.string.mr_controller_play;
1218692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1219692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    // Announce the action for accessibility.
1220692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (mAccessibilityManager != null && mAccessibilityManager.isEnabled()
1221692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            && actionDescResId != 0) {
1222692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        AccessibilityEvent event = AccessibilityEvent.obtain(
1223692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                                AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
1224692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        event.setPackageName(mContext.getPackageName());
1225692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        event.setClassName(getClass().getName());
122692fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                        event.getText().add(
122792fd9a9e07a33a01d12ef9c47f73b2c7193a5fd9Christofer Ã…kersten                                ApiHelper.getLibResources(mContext).getString(actionDescResId));
1228692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        mAccessibilityManager.sendAccessibilityEvent(event);
1229692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1230692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1231692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else if (id == R.id.mr_close) {
1232692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                dismiss();
1233692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1234692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1235692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1236692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1237692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private class VolumeChangeListener implements SeekBar.OnSeekBarChangeListener {
1238692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private final Runnable mStopTrackingTouch = new Runnable() {
1239692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            @Override
1240692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            public void run() {
1241692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (mRouteInVolumeSliderTouched != null) {
1242692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    mRouteInVolumeSliderTouched = null;
1243692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (mHasPendingUpdate) {
1244692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        update(mPendingUpdateAnimationNeeded);
1245692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1246692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1247692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1248692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        };
1249692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1250692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        VolumeChangeListener() {
1251692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1252692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1253692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1254692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onStartTrackingTouch(SeekBar seekBar) {
1255692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mRouteInVolumeSliderTouched != null) {
1256692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeSlider.removeCallbacks(mStopTrackingTouch);
1257692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1258692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mRouteInVolumeSliderTouched = (MediaRouter.RouteInfo) seekBar.getTag();
1259692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1260692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1261692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1262692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onStopTrackingTouch(SeekBar seekBar) {
1263692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            // Defer resetting mVolumeSliderTouched to allow the media route provider
1264692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            // a little time to settle into its new state and publish the final
1265692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            // volume update.
1266692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
1267692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1268692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1269692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1270692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
1271692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (fromUser) {
1272692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                MediaRouter.RouteInfo route = (MediaRouter.RouteInfo) seekBar.getTag();
1273692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (DEBUG) {
1274692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    Log.d(TAG, "onProgressChanged(): calling "
1275692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            + "MediaRouter.RouteInfo.requestSetVolume(" + progress + ")");
1276692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1277692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                route.requestSetVolume(progress);
1278692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1279692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1280692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1281692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1282692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> {
1283692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        final float mDisabledAlpha;
1284692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1285692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public VolumeGroupAdapter(Context context, List<MediaRouter.RouteInfo> objects) {
1286692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            super(context, 0, objects);
1287692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mDisabledAlpha = MediaRouterThemeHelper.getDisabledAlpha(context);
1288692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1289692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1290692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1291692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public boolean isEnabled(int position) {
1292692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return false;
1293692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1294692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1295692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1296692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public View getView(final int position, View convertView, ViewGroup parent) {
1297692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            View v = convertView;
1298692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (v == null) {
1299692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                v = LayoutInflater.from(parent.getContext()).inflate(
1300692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        R.layout.mr_controller_volume_item, parent, false);
1301692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
1302692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                updateVolumeGroupItemHeight(v);
1303692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1304692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1305692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            MediaRouter.RouteInfo route = getItem(position);
1306692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (route != null) {
1307692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                boolean isEnabled = route.isEnabled();
1308692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1309692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                TextView routeName = (TextView) v.findViewById(R.id.mr_name);
1310692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                routeName.setEnabled(isEnabled);
1311692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                routeName.setText(route.getName());
1312692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1313692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                MediaRouteVolumeSlider volumeSlider =
1314692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        (MediaRouteVolumeSlider) v.findViewById(R.id.mr_volume_slider);
1315692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                MediaRouterThemeHelper.setVolumeSliderColor(
1316692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        parent.getContext(), volumeSlider, mVolumeGroupList);
1317692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                volumeSlider.setTag(route);
1318692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mVolumeSliderMap.put(route, volumeSlider);
1319692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                volumeSlider.setHideThumb(!isEnabled);
1320692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                volumeSlider.setEnabled(isEnabled);
1321692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (isEnabled) {
1322692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (isVolumeControlAvailable(route)) {
1323692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        volumeSlider.setMax(route.getVolumeMax());
1324692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        volumeSlider.setProgress(route.getVolume());
1325692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        volumeSlider.setOnSeekBarChangeListener(mVolumeChangeListener);
1326692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    } else {
1327692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        volumeSlider.setMax(100);
1328692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        volumeSlider.setProgress(100);
1329692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        volumeSlider.setEnabled(false);
1330692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1331692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1332692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1333692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                ImageView volumeItemIcon =
1334692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        (ImageView) v.findViewById(R.id.mr_volume_item_icon);
1335692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                volumeItemIcon.setAlpha(isEnabled ? 0xFF : (int) (0xFF * mDisabledAlpha));
1336692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1337692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // If overlay bitmap exists, real view should remain hidden until
1338692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // the animation ends.
1339692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                LinearLayout container = (LinearLayout) v.findViewById(R.id.volume_item_container);
1340692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                container.setVisibility(mGroupMemberRoutesAnimatingWithBitmap.contains(route)
1341692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        ? View.INVISIBLE : View.VISIBLE);
1342692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1343692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // Routes which are being added will be invisible until animation ends.
1344692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                if (mGroupMemberRoutesAdded != null && mGroupMemberRoutesAdded.contains(route)) {
1345692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    Animation alphaAnim = new AlphaAnimation(0.0f, 0.0f);
1346692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    alphaAnim.setDuration(0);
1347692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    alphaAnim.setFillEnabled(true);
1348692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    alphaAnim.setFillAfter(true);
1349692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    v.clearAnimation();
1350692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    v.startAnimation(alphaAnim);
1351692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1352692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1353692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return v;
1354692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1355692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1356692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1357692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    private class FetchArtTask extends AsyncTask<Void, Void, Bitmap> {
1358692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        // Show animation only when fetching takes a long time.
1359692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private static final long SHOW_ANIM_TIME_THRESHOLD_MILLIS = 120L;
1360692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1361692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private final Bitmap mIconBitmap;
1362692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private final Uri mIconUri;
1363692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private int mBackgroundColor;
1364692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private long mStartTimeMillis;
1365692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1366692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        FetchArtTask() {
1367692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Bitmap bitmap = mDescription == null ? null : mDescription.getIconBitmap();
1368692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (isBitmapRecycled(bitmap)) {
1369692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Log.w(TAG, "Can't fetch the given art bitmap because it's already recycled.");
1370692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                bitmap = null;
1371692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1372692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mIconBitmap = bitmap;
1373692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mIconUri = mDescription == null ? null : mDescription.getIconUri();
1374692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1375692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1376692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public Bitmap getIconBitmap() {
1377692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return mIconBitmap;
1378692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1379692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1380692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        public Uri getIconUri() {
1381692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return mIconUri;
1382692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1383692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1384692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1385692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        protected void onPreExecute() {
1386692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mStartTimeMillis = SystemClock.uptimeMillis();
1387692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            clearLoadedBitmap();
1388692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1389692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1390692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1391692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        protected Bitmap doInBackground(Void... arg) {
1392692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            Bitmap art = null;
1393692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (mIconBitmap != null) {
1394692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                art = mIconBitmap;
1395692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else if (mIconUri != null) {
1396692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                InputStream stream = null;
1397692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                try {
1398692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if ((stream = openInputStreamByScheme(mIconUri)) == null) {
1399692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        Log.w(TAG, "Unable to open: " + mIconUri);
1400692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        return null;
1401692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1402692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    // Query art size.
1403692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    BitmapFactory.Options options = new BitmapFactory.Options();
1404692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    options.inJustDecodeBounds = true;
1405692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    BitmapFactory.decodeStream(stream, null, options);
1406692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (options.outWidth == 0 || options.outHeight == 0) {
1407692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        return null;
1408692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1409692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    // Rewind the stream in order to restart art decoding.
1410692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    try {
1411692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        stream.reset();
1412692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    } catch (IOException e) {
1413692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        // Failed to rewind the stream, try to reopen it.
1414692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        stream.close();
1415692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        if ((stream = openInputStreamByScheme(mIconUri)) == null) {
1416692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            Log.w(TAG, "Unable to open: " + mIconUri);
1417692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            return null;
1418692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        }
1419692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1420692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    // Calculate required size to decode the art and possibly resize it.
1421692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    options.inJustDecodeBounds = false;
1422692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    int reqHeight = getDesiredArtHeight(options.outWidth, options.outHeight);
1423692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    int ratio = options.outHeight / reqHeight;
1424692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    options.inSampleSize = Math.max(1, Integer.highestOneBit(ratio));
1425692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (isCancelled()) {
1426692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        return null;
1427692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1428692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    art = BitmapFactory.decodeStream(stream, null, options);
1429692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                } catch (IOException e){
1430692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    Log.w(TAG, "Unable to open: " + mIconUri, e);
1431692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                } finally {
1432692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    if (stream != null) {
1433692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        try {
1434692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                            stream.close();
1435692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        } catch (IOException e) {
1436692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        }
1437692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    }
1438692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                }
1439692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1440692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (isBitmapRecycled(art)) {
1441692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Log.w(TAG, "Can't use recycled bitmap: " + art);
1442692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                return null;
1443692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1444692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (art != null && art.getWidth() < art.getHeight()) {
1445692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // Portrait art requires dominant color as background color.
1446692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                Palette palette = new Palette.Builder(art).maximumColorCount(1).generate();
1447692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mBackgroundColor = palette.getSwatches().isEmpty()
1448692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                        ? 0 : palette.getSwatches().get(0).getRgb();
1449692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1450692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return art;
1451692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1452692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1453692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        @Override
1454692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        protected void onPostExecute(Bitmap art) {
1455692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            mFetchArtTask = null;
1456692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (!ObjectsCompat.equals(mArtIconBitmap, mIconBitmap)
1457692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    || !ObjectsCompat.equals(mArtIconUri, mIconUri)) {
1458692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtIconBitmap = mIconBitmap;
1459692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtIconLoadedBitmap = art;
1460692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtIconUri = mIconUri;
1461692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtIconBackgroundColor = mBackgroundColor;
1462692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                mArtIconIsLoaded = true;
1463692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                long elapsedTimeMillis = SystemClock.uptimeMillis() - mStartTimeMillis;
1464692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                // Loaded bitmap will be applied on the next update
1465692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                update(elapsedTimeMillis > SHOW_ANIM_TIME_THRESHOLD_MILLIS);
1466692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1467692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1468692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim
1469692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        private InputStream openInputStreamByScheme(Uri uri) throws IOException {
1470692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            String scheme = uri.getScheme().toLowerCase();
1471692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            InputStream stream = null;
1472692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)
1473692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    || ContentResolver.SCHEME_CONTENT.equals(scheme)
1474692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                    || ContentResolver.SCHEME_FILE.equals(scheme)) {
1475692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                stream = mContext.getContentResolver().openInputStream(uri);
1476692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            } else {
1477692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                URL url = new URL(uri.toString());
1478692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                URLConnection conn = url.openConnection();
1479692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                conn.setConnectTimeout(CONNECTION_TIMEOUT_MILLIS);
1480692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                conn.setReadTimeout(CONNECTION_TIMEOUT_MILLIS);
1481692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim                stream = conn.getInputStream();
1482692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            }
1483692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim            return (stream == null) ? null : new BufferedInputStream(stream);
1484692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim        }
1485692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim    }
1486692a547730bbc95ad277d5214ef3d786ce1e499fSungsoo Lim}
1487