Refactor the layout of media route controller dialog

- Apply the UX layout size for the media route control frame and volume layout.
- Remove outer ScrollView.
- Split media route control frame into several views for making easy to handle
  the group expansion UX.
- Update play and pause control icons with 48*48 size.
- Make the close button always shown.

Bug: 23117610
Change-Id: I5022a45761c99cc0e046b041e1798740c0adaeb4
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_pause_dark.png b/v7/mediarouter/res/drawable-hdpi/ic_pause_dark.png
index 81c32fe..7192ad4 100644
--- a/v7/mediarouter/res/drawable-hdpi/ic_pause_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/ic_pause_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_pause_light.png b/v7/mediarouter/res/drawable-hdpi/ic_pause_light.png
index 864d8d2..aeb13eb 100644
--- a/v7/mediarouter/res/drawable-hdpi/ic_pause_light.png
+++ b/v7/mediarouter/res/drawable-hdpi/ic_pause_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_play_dark.png b/v7/mediarouter/res/drawable-hdpi/ic_play_dark.png
index 568ae86..547ef30 100644
--- a/v7/mediarouter/res/drawable-hdpi/ic_play_dark.png
+++ b/v7/mediarouter/res/drawable-hdpi/ic_play_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-hdpi/ic_play_light.png b/v7/mediarouter/res/drawable-hdpi/ic_play_light.png
index e278033..0648523 100644
--- a/v7/mediarouter/res/drawable-hdpi/ic_play_light.png
+++ b/v7/mediarouter/res/drawable-hdpi/ic_play_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_pause_dark.png b/v7/mediarouter/res/drawable-mdpi/ic_pause_dark.png
index c4218a4..f49aed7 100644
--- a/v7/mediarouter/res/drawable-mdpi/ic_pause_dark.png
+++ b/v7/mediarouter/res/drawable-mdpi/ic_pause_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_pause_light.png b/v7/mediarouter/res/drawable-mdpi/ic_pause_light.png
index ab26a30..6708b41 100644
--- a/v7/mediarouter/res/drawable-mdpi/ic_pause_light.png
+++ b/v7/mediarouter/res/drawable-mdpi/ic_pause_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_play_dark.png b/v7/mediarouter/res/drawable-mdpi/ic_play_dark.png
index 4446faa..a3c80e7 100644
--- a/v7/mediarouter/res/drawable-mdpi/ic_play_dark.png
+++ b/v7/mediarouter/res/drawable-mdpi/ic_play_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-mdpi/ic_play_light.png b/v7/mediarouter/res/drawable-mdpi/ic_play_light.png
index 55b8c5e..8f6a725 100644
--- a/v7/mediarouter/res/drawable-mdpi/ic_play_light.png
+++ b/v7/mediarouter/res/drawable-mdpi/ic_play_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_pause_dark.png b/v7/mediarouter/res/drawable-xhdpi/ic_pause_dark.png
index bd7ec0f..660ac65 100644
--- a/v7/mediarouter/res/drawable-xhdpi/ic_pause_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_pause_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_pause_light.png b/v7/mediarouter/res/drawable-xhdpi/ic_pause_light.png
index e79d7d7..239b5a8 100644
--- a/v7/mediarouter/res/drawable-xhdpi/ic_pause_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_pause_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_play_dark.png b/v7/mediarouter/res/drawable-xhdpi/ic_play_dark.png
index 9a5d45f..be5c062 100644
--- a/v7/mediarouter/res/drawable-xhdpi/ic_play_dark.png
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_play_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xhdpi/ic_play_light.png b/v7/mediarouter/res/drawable-xhdpi/ic_play_light.png
index acaeca6..4be0ef3 100644
--- a/v7/mediarouter/res/drawable-xhdpi/ic_play_light.png
+++ b/v7/mediarouter/res/drawable-xhdpi/ic_play_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_pause_dark.png b/v7/mediarouter/res/drawable-xxhdpi/ic_pause_dark.png
index 2a96557..3ea7e03 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/ic_pause_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_pause_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_pause_light.png b/v7/mediarouter/res/drawable-xxhdpi/ic_pause_light.png
index bf2560f..78456c7 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/ic_pause_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_pause_light.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_play_dark.png b/v7/mediarouter/res/drawable-xxhdpi/ic_play_dark.png
index 1ec1995..2745c3a 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/ic_play_dark.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_play_dark.png
Binary files differ
diff --git a/v7/mediarouter/res/drawable-xxhdpi/ic_play_light.png b/v7/mediarouter/res/drawable-xxhdpi/ic_play_light.png
index a5bd8df..27a0dc0 100644
--- a/v7/mediarouter/res/drawable-xxhdpi/ic_play_light.png
+++ b/v7/mediarouter/res/drawable-xxhdpi/ic_play_light.png
Binary files differ
diff --git a/v7/mediarouter/res/layout/mr_controller_material_dialog_b.xml b/v7/mediarouter/res/layout/mr_controller_material_dialog_b.xml
index d01d251..a4d127d 100644
--- a/v7/mediarouter/res/layout/mr_controller_material_dialog_b.xml
+++ b/v7/mediarouter/res/layout/mr_controller_material_dialog_b.xml
@@ -14,117 +14,61 @@
      limitations under the License.
 -->
 
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content">
-    <LinearLayout android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-        <LinearLayout android:id="@+id/title_bar"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:paddingLeft="24dp"
-                android:paddingRight="24dp"
-                android:orientation="horizontal" >
-            <TextView android:id="@+id/route_name"
-                    android:layout_width="0dp"
-                    android:layout_height="72dp"
-                    android:layout_weight="1"
-                    android:gravity="center_vertical"
-                    android:singleLine="true"
-                    android:ellipsize="end"
-                    android:textAppearance="?attr/mediaRouteControllerTitleTextStyle" />
-            <ImageButton android:id="@+id/close"
-                    android:layout_width="24dp"
-                    android:layout_height="24dp"
-                    android:layout_marginLeft="12dp"
-                    android:layout_gravity="center_vertical"
-                    android:contentDescription="@string/mr_controller_close_description"
-                    android:src="?attr/mediaRouteCloseDrawable"
-                    android:background="?attr/selectableItemBackgroundBorderless" />
-        </LinearLayout>
-        <FrameLayout android:id="@+id/media_route_control_frame"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" >
-            <RelativeLayout android:id="@+id/default_control_frame"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:background="?attr/colorPrimary">
-                <ImageView android:id="@+id/art"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:adjustViewBounds="true"
-                        android:scaleType="fitCenter"/>
-                <ImageButton android:id="@+id/play_pause"
-                        android:layout_width="48dip"
-                        android:layout_height="48dip"
-                        android:padding="12dip"
-                        android:layout_marginTop="8dip"
-                        android:layout_marginBottom="8dip"
-                        android:layout_alignParentRight="true"
-                        android:layout_below="@id/art"
-                        android:contentDescription="@string/mr_controller_play"
-                        android:background="?attr/selectableItemBackgroundBorderless"/>
-                <LinearLayout android:orientation="vertical"
-                        android:layout_height="wrap_content"
-                        android:layout_width="wrap_content"
-                        android:minHeight="64dip"
-                        android:layout_marginLeft="24dip"
-                        android:gravity="center_vertical"
-                        android:layout_toLeftOf="@id/play_pause"
-                        android:layout_below="@id/art"
-                        android:layout_alignParentLeft="true" >
-                    <TextView android:id="@+id/title"
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:textAppearance="?attr/mediaRouteControllerPrimaryTextStyle"
-                            android:singleLine="true" />
-                    <TextView android:id="@+id/subtitle"
-                            android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
-                            android:textAppearance="?attr/mediaRouteControllerSecondaryTextStyle"
-                            android:singleLine="true" />
-                </LinearLayout>
-            </RelativeLayout>
-        </FrameLayout>
-        <!-- Optional volume slider section. -->
-        <LinearLayout android:id="@+id/media_route_volume_layout"
-                      android:layout_width="fill_parent"
-                      android:layout_height="64dp"
-                      android:gravity="center_vertical"
-                      android:padding="8dp"
-                      android:visibility="gone"
-                      android:background="?attr/colorPrimary">
-            <ImageView android:layout_width="48dp"
-                       android:layout_height="48dp"
-                       android:src="?attr/mediaRouteCastDrawable"
-                       android:gravity="center"
-                       android:scaleType="center" />
-            <SeekBar android:id="@+id/media_route_volume_slider"
-                     android:layout_width="0dp"
-                     android:layout_height="wrap_content"
-                     android:layout_weight="1"
-                     android:layout_marginLeft="8dp"
-                     android:layout_marginRight="8dp" />
-            <ImageButton android:id="@+id/media_route_group_expand_collapse"
-                         android:layout_width="48dip"
-                         android:layout_height="48dip"
-                         android:padding="12dip"
-                         android:contentDescription="@string/mr_controller_expand_group"
-                         android:src="?attr/mediaRouteExpandGroupDrawable"
-                         android:background="?attr/selectableItemBackgroundBorderless"
-                         android:visibility="gone"/>
-        </LinearLayout>
-        <ListView android:id="@+id/media_route_volume_group_list"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="vertical">
+    <LinearLayout android:id="@+id/title_bar"
+                  android:layout_width="match_parent"
+                  android:layout_height="wrap_content"
+                  android:paddingLeft="24dp"
+                  android:paddingRight="24dp"
+                  android:orientation="horizontal" >
+        <TextView android:id="@+id/route_name"
+                  android:layout_width="0dp"
+                  android:layout_height="72dp"
+                  android:layout_weight="1"
+                  android:gravity="center_vertical"
+                  android:singleLine="true"
+                  android:ellipsize="end"
+                  android:textAppearance="?attr/mediaRouteControllerTitleTextStyle" />
+        <ImageButton android:id="@+id/close"
+                     android:layout_width="24dp"
+                     android:layout_height="24dp"
+                     android:layout_marginLeft="12dp"
+                     android:layout_gravity="center_vertical"
+                     android:contentDescription="@string/mr_controller_close_description"
+                     android:src="?attr/mediaRouteCloseDrawable"
+                     android:background="?attr/selectableItemBackgroundBorderless" />
+    </LinearLayout>
+    <FrameLayout android:id="@+id/custom_control_frame"
+                 android:layout_width="match_parent"
+                 android:layout_height="wrap_content"
+                 android:visibility="gone" />
+    <ImageView android:id="@+id/mr_art"
+               android:layout_width="match_parent"
+               android:layout_height="wrap_content"
+               android:adjustViewBounds="true"
+               android:scaleType="fitCenter"
+               android:background="?attr/colorPrimary" />
+    <ListView android:id="@+id/mr_control"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:paddingTop="16dp"
+              android:paddingBottom="16dp"
+              android:divider="?attr/colorPrimary"
+              android:dividerHeight="8dp"
+              android:background="?attr/colorPrimary" />
+    <ListView android:id="@+id/mr_volume_group_list"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:background="?attr/colorPrimaryDark"
+              android:visibility="gone" />
+    <LinearLayout android:id="@+id/buttons"
                   android:layout_width="fill_parent"
                   android:layout_height="wrap_content"
-                  android:visibility="gone">
-        </ListView>
-        <LinearLayout android:id="@+id/buttons"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal" >
-            <Button android:id="@+id/disconnect"
+                  android:orientation="horizontal">
+        <Button android:id="@+id/disconnect"
                 android:layout_width="0dp"
                 android:layout_height="48dp"
                 android:gravity="center"
@@ -132,7 +76,7 @@
                 android:background="?attr/selectableItemBackgroundBorderless"
                 android:text="@string/mr_controller_disconnect"
                 android:visibility="gone" />
-            <Button android:id="@+id/stop"
+        <Button android:id="@+id/stop"
                 android:layout_width="0dp"
                 android:layout_height="48dp"
                 android:gravity="center"
@@ -140,6 +84,5 @@
                 android:textColor="?attr/colorAccent"
                 android:background="?attr/selectableItemBackgroundBorderless"
                 android:text="@string/mr_controller_stop" />
-        </LinearLayout>
     </LinearLayout>
-</ScrollView>
+</LinearLayout>
diff --git a/v7/mediarouter/res/layout/mr_controller_volume_item.xml b/v7/mediarouter/res/layout/mr_controller_volume_item.xml
index d07d94b..8202810 100644
--- a/v7/mediarouter/res/layout/mr_controller_volume_item.xml
+++ b/v7/mediarouter/res/layout/mr_controller_volume_item.xml
@@ -18,24 +18,24 @@
               android:layout_width="fill_parent"
               android:layout_height="64dp"
               android:padding="8dp">
-    <TextView android:id="@+id/media_route_name"
+    <TextView android:id="@+id/mr_name"
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:layout_alignParentTop="true"
               android:layout_alignParentLeft="true" />
-    <ImageView android:id="@+id/media_route_volume_item_icon"
+    <ImageView android:id="@+id/mr_volume_item_icon"
                android:layout_width="48dp"
                android:layout_height="48dp"
-               android:layout_below="@id/media_route_name"
+               android:layout_below="@id/mr_name"
                android:layout_alignParentLeft="true"
                android:src="?attr/mediaRouteAudioTrackDrawable"
                android:gravity="center"
                android:scaleType="center" />
-    <SeekBar android:id="@+id/media_route_volume_slider"
+    <SeekBar android:id="@+id/mr_volume_slider"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
-             android:layout_below="@id/media_route_name"
-             android:layout_toRightOf="@id/media_route_volume_item_icon"
+             android:layout_below="@id/mr_name"
+             android:layout_toRightOf="@id/mr_volume_item_icon"
              android:layout_gravity="center_vertical"
              android:layout_marginTop="8dp"
              android:layout_marginLeft="8dp"
diff --git a/v7/mediarouter/res/layout/mr_playback_control.xml b/v7/mediarouter/res/layout/mr_playback_control.xml
new file mode 100644
index 0000000..28b2333
--- /dev/null
+++ b/v7/mediarouter/res/layout/mr_playback_control.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal"
+                android:background="?attr/colorPrimary">
+    <ImageButton android:id="@+id/mr_control_play_pause"
+                 android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:layout_marginLeft="12dp"
+                 android:layout_marginRight="12dp"
+                 android:layout_alignParentRight="true"
+                 android:layout_centerInParent="true"
+                 android:contentDescription="@string/mr_controller_play"
+                 android:background="?attr/selectableItemBackgroundBorderless"/>
+    <LinearLayout android:orientation="vertical"
+                  android:layout_height="fill_parent"
+                  android:layout_width="wrap_content"
+                  android:layout_marginLeft="24dp"
+                  android:layout_alignParentLeft="true"
+                  android:layout_toLeftOf="@id/mr_control_play_pause"
+                  android:layout_centerInParent="true">
+        <TextView android:id="@+id/mr_control_title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:textAppearance="?attr/mediaRouteControllerPrimaryTextStyle"
+                  android:singleLine="true" />
+        <TextView android:id="@+id/mr_control_subtitle"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:textAppearance="?attr/mediaRouteControllerSecondaryTextStyle"
+                  android:singleLine="true" />
+    </LinearLayout>
+</RelativeLayout>
diff --git a/v7/mediarouter/res/layout/mr_volume_control.xml b/v7/mediarouter/res/layout/mr_volume_control.xml
new file mode 100644
index 0000000..18fa7fd
--- /dev/null
+++ b/v7/mediarouter/res/layout/mr_volume_control.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="fill_parent"
+              android:layout_height="wrap_content"
+              android:minHeight="48dp"
+              android:gravity="center_vertical"
+              android:paddingLeft="24dp"
+              android:paddingRight="24dp"
+              android:background="?attr/colorPrimary">
+    <ImageView android:layout_width="24dp"
+               android:layout_height="24dp"
+               android:src="?attr/mediaRouteCastDrawable"
+               android:gravity="center"
+               android:scaleType="center" />
+    <SeekBar android:id="@+id/mr_volume_slider"
+             android:layout_width="0dp"
+             android:layout_height="wrap_content"
+             android:layout_weight="1" />
+    <ImageButton android:id="@+id/mr_group_expand_collapse"
+                 android:layout_width="24dp"
+                 android:layout_height="24dp"
+                 android:contentDescription="@string/mr_controller_expand_group"
+                 android:src="?attr/mediaRouteExpandGroupDrawable"
+                 android:background="?attr/selectableItemBackgroundBorderless"
+                 android:visibility="gone"/>
+</LinearLayout>
diff --git a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
index 661c3e6..7bdafe3 100644
--- a/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
+++ b/v7/mediarouter/src/android/support/v7/app/MediaRouteControllerDialog.java
@@ -16,8 +16,6 @@
 
 package android.support.v7.app;
 
-import static android.widget.SeekBar.OnSeekBarChangeListener;
-
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -54,13 +52,17 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListView;
+import android.widget.RelativeLayout;
 import android.widget.SeekBar;
 import android.widget.TextView;
 
 import java.io.BufferedInputStream;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 
+import static android.widget.SeekBar.OnSeekBarChangeListener;
+
 /**
  * This class implements the route controller dialog for {@link MediaRouter}.
  * <p>
@@ -92,24 +94,20 @@
     private int mDialogWidthLandscape;
     private int mDialogPaddingVertical;
 
-    private View mControlView;
+    private View mCustomControlView;
 
     private Button mDisconnectButton;
     private Button mStopCastingButton;
-    private ImageButton mPlayPauseButton;
     private ImageButton mCloseButton;
-    private ImageButton mGroupExpandCollapseButton;
 
+    private FrameLayout mCustomControlFrame;
     private ImageView mArtView;
-    private TextView mTitleView;
-    private TextView mSubtitleView;
-    private TextView mRouteNameView;
+    private TextView mRouteNameTextView;
 
     private boolean mVolumeControlEnabled = true;
-    private LinearLayout mVolumeLayout;
+    private MediaRouteControlAdapter mControlAdapter;
+    private ListView mControlView;
     private ListView mVolumeGroupList;
-    private SeekBar mVolumeSlider;
-    private boolean mVolumeSliderTouched;
 
     private MediaControllerCompat mMediaController;
     private MediaControllerCallback mControllerCallback;
@@ -165,7 +163,7 @@
      * @return The media control view, or null if none.
      */
     public View getMediaControlView() {
-        return mControlView;
+        return mCustomControlView;
     }
 
     /**
@@ -179,7 +177,7 @@
         if (mVolumeControlEnabled != enable) {
             mVolumeControlEnabled = enable;
             if (mCreated) {
-                updateVolume();
+                mControlAdapter.updateVolumeControl();
             }
         }
     }
@@ -256,92 +254,27 @@
         mStopCastingButton = (Button) findViewById(R.id.stop);
         mStopCastingButton.setOnClickListener(listener);
 
+        mRouteNameTextView = (TextView) findViewById(R.id.route_name);
         mCloseButton = (ImageButton) findViewById(R.id.close);
         mCloseButton.setOnClickListener(listener);
 
-        mArtView = (ImageView) findViewById(R.id.art);
-        mTitleView = (TextView) findViewById(R.id.title);
-        mSubtitleView = (TextView) findViewById(R.id.subtitle);
-        mPlayPauseButton = (ImageButton) findViewById(R.id.play_pause);
-        mPlayPauseButton.setOnClickListener(listener);
-        mRouteNameView = (TextView) findViewById(R.id.route_name);
-        mVolumeLayout = (LinearLayout)findViewById(R.id.media_route_volume_layout);
-        mVolumeGroupList = (ListView)findViewById(R.id.media_route_volume_group_list);
+        mCustomControlFrame = (FrameLayout) findViewById(R.id.custom_control_frame);
+        mArtView = (ImageView) findViewById(R.id.mr_art);
 
-        TypedArray styledAttributes = getContext().obtainStyledAttributes(new int[] {
-                R.attr.mediaRouteExpandGroupDrawable,
-                R.attr.mediaRouteCollapseGroupDrawable
-        });
-        final Drawable expandGroupDrawable = styledAttributes.getDrawable(0);
-        final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1);
-        styledAttributes.recycle();
-
-        mGroupExpandCollapseButton = (ImageButton)findViewById(
-                R.id.media_route_group_expand_collapse);
-        mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() {
-            private boolean mIsExpanded;
-
-            @Override
-            public void onClick(View v) {
-                mIsExpanded = !mIsExpanded;
-                if (mIsExpanded) {
-                    mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable);
-                    mVolumeGroupList.setVisibility(View.VISIBLE);
-                    mVolumeGroupList.setAdapter(
-                            new VolumeGroupAdapter(getContext(), getGroup().getRoutes()));
-                } else {
-                    mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable);
-                    mVolumeGroupList.setVisibility(View.GONE);
-                }
-            }
-        });
-        mVolumeSlider = (SeekBar)findViewById(R.id.media_route_volume_slider);
-        mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
-            private final Runnable mStopTrackingTouch = new Runnable() {
-                @Override
-                public void run() {
-                    if (mVolumeSliderTouched) {
-                        mVolumeSliderTouched = false;
-                        updateVolume();
-                    }
-                }
-            };
-
-            @Override
-            public void onStartTrackingTouch(SeekBar seekBar) {
-                if (mVolumeSliderTouched) {
-                    mVolumeSlider.removeCallbacks(mStopTrackingTouch);
-                } else {
-                    mVolumeSliderTouched = true;
-                }
-            }
-
-            @Override
-            public void onStopTrackingTouch(SeekBar seekBar) {
-                // Defer resetting mVolumeSliderTouched to allow the media route provider
-                // a little time to settle into its new state and publish the final
-                // volume update.
-                mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
-            }
-
-            @Override
-            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
-                if (fromUser) {
-                    mRoute.requestSetVolume(progress);
-                }
-            }
-        });
+        mControlAdapter = new MediaRouteControlAdapter(
+                getContext(), new ArrayList<View>(), listener);
+        mControlView = (ListView) findViewById(R.id.mr_control);
+        mControlView.setAdapter(mControlAdapter);
+        mVolumeGroupList = (ListView)findViewById(R.id.mr_volume_group_list);
 
         mCreated = true;
-        if (update()) {
-            mControlView = onCreateMediaControlView(savedInstanceState);
-            FrameLayout controlFrame =
-                    (FrameLayout)findViewById(R.id.media_route_control_frame);
-            if (mControlView != null) {
-                controlFrame.findViewById(R.id.default_control_frame).setVisibility(View.GONE);
-                controlFrame.addView(mControlView);
-            }
+        mCustomControlView = onCreateMediaControlView(savedInstanceState);
+        if (mCustomControlView != null) {
+            mCustomControlFrame.addView(mCustomControlView);
+            mCustomControlFrame.setVisibility(View.VISIBLE);
+            mArtView.setVisibility(View.GONE);
         }
+        update();
     }
 
     /**
@@ -402,108 +335,28 @@
         return super.onKeyUp(keyCode, event);
     }
 
-    private boolean update() {
+    private void update() {
         if (!mRoute.isSelected() || mRoute.isDefault()) {
             dismiss();
-            return false;
+            return;
         }
         if (!mCreated) {
-            return false;
+            return;
         }
 
-        updateVolume();
+        mRouteNameTextView.setText(mRoute.getName());
+        mDisconnectButton.setVisibility(mRoute.canDisconnect() ? View.VISIBLE : View.GONE);
 
-        mRouteNameView.setText(mRoute.getName());
-
-        if (mRoute.canDisconnect()) {
-            mDisconnectButton.setVisibility(View.VISIBLE);
-        } else {
-            mDisconnectButton.setVisibility(View.GONE);
-        }
-
-        if (mRoute.getSettingsIntent() != null) {
-            mCloseButton.setVisibility(View.VISIBLE);
-        } else {
-            mCloseButton.setVisibility(View.GONE);
-        }
-
-        if (mControlView == null) {
+        if (mCustomControlView == null) {
             if (mFetchArtTask != null) {
                 mFetchArtTask.cancel(true);
             }
             mArtView.setVisibility(View.GONE);
             mFetchArtTask = new FetchArtTask();
             mFetchArtTask.execute();
-
-            CharSequence title = mDescription == null ? null : mDescription.getTitle();
-            boolean hasTitle = !TextUtils.isEmpty(title);
-
-            CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle();
-            boolean hasSubtitle = !TextUtils.isEmpty(subtitle);
-
-            if (!hasTitle && !hasSubtitle) {
-                mTitleView.setText(R.string.mr_controller_no_info_available);
-                mTitleView.setEnabled(false);
-                mTitleView.setVisibility(View.VISIBLE);
-                mSubtitleView.setVisibility(View.GONE);
-            } else {
-                mTitleView.setText(title);
-                mTitleView.setEnabled(hasTitle);
-                mTitleView.setVisibility(hasTitle ? View.VISIBLE : View.GONE);
-                mSubtitleView.setText(subtitle);
-                mSubtitleView.setVisibility(hasSubtitle ? View.VISIBLE : View.GONE);
-            }
-            if (mState != null) {
-                boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
-                        || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
-                boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
-                        | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
-                boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
-                                | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
-                if (isPlaying && supportsPause) {
-                    mPlayPauseButton.setVisibility(View.VISIBLE);
-                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
-                            getContext(), R.attr.mediaRoutePauseDrawable));
-                    mPlayPauseButton.setContentDescription(getContext().getResources()
-                            .getText(R.string.mr_controller_pause));
-                } else if (!isPlaying && supportsPlay) {
-                    mPlayPauseButton.setVisibility(View.VISIBLE);
-                    mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
-                            getContext(), R.attr.mediaRoutePlayDrawable));
-                    mPlayPauseButton.setContentDescription(getContext().getResources()
-                            .getText(R.string.mr_controller_play));
-                } else {
-                    mPlayPauseButton.setVisibility(View.GONE);
-                }
-            } else {
-                mPlayPauseButton.setVisibility(View.GONE);
-            }
         }
-        return true;
-    }
-
-    private void updateVolume() {
-        if (!mVolumeSliderTouched) {
-            if (isVolumeControlAvailable()) {
-                mVolumeLayout.setVisibility(View.VISIBLE);
-                mVolumeSlider.setMax(mRoute.getVolumeMax());
-                mVolumeSlider.setProgress(mRoute.getVolume());
-                if (USE_GROUP) {
-                    if (getGroup() == null) {
-                        mGroupExpandCollapseButton.setVisibility(View.GONE);
-                    } else {
-                        mGroupExpandCollapseButton.setVisibility(View.VISIBLE);
-                        VolumeGroupAdapter adapter =
-                                (VolumeGroupAdapter) mVolumeGroupList.getAdapter();
-                        if (adapter != null) {
-                            adapter.notifyDataSetChanged();
-                        }
-                    }
-                }
-            } else {
-                mVolumeLayout.setVisibility(View.GONE);
-            }
-        }
+        mControlAdapter.updateVolumeControl();
+        mControlAdapter.updatePlaybackControl();
     }
 
     private boolean isVolumeControlAvailable() {
@@ -568,7 +421,7 @@
         @Override
         public void onRouteVolumeChanged(MediaRouter router, MediaRouter.RouteInfo route) {
             if (route == mRoute) {
-                updateVolume();
+                mControlAdapter.updateVolumeControl();
             }
         }
     }
@@ -606,7 +459,7 @@
                             MediaRouter.UNSELECT_REASON_DISCONNECTED);
                 }
                 dismiss();
-            } else if (id == R.id.play_pause) {
+            } else if (id == R.id.mr_control_play_pause) {
                 if (mMediaController != null && mState != null) {
                     if (mState.getState() == PlaybackStateCompat.STATE_PLAYING) {
                         mMediaController.getTransportControls().pause();
@@ -620,6 +473,190 @@
         }
     }
 
+    // TODO: Consider to implement the default controls using LinearLayout instead of ListView.
+    private class MediaRouteControlAdapter extends ArrayAdapter<View> {
+        private List<View> mItemViews;
+
+        private RelativeLayout mPlaybackControl;
+        private TextView mTitleView;
+        private TextView mSubtitleView;
+        private ImageButton mPlayPauseButton;
+
+        private LinearLayout mVolumeControl;
+        private SeekBar mVolumeSlider;
+        private ImageButton mGroupExpandCollapseButton;
+        private boolean mVolumeSliderTouched;
+
+
+        public MediaRouteControlAdapter(Context context, List<View> itemViews,
+                ClickListener listener) {
+            super(context, 0, itemViews);
+            mItemViews = itemViews;
+
+            mPlaybackControl = (RelativeLayout) LayoutInflater.from(context).inflate(
+                    R.layout.mr_playback_control, mControlView);
+            mTitleView = (TextView) mPlaybackControl.findViewById(R.id.mr_control_title);
+            mSubtitleView = (TextView) mPlaybackControl.findViewById(R.id.mr_control_subtitle);
+            mPlayPauseButton = (ImageButton) mPlaybackControl.findViewById(
+                    R.id.mr_control_play_pause);
+            mPlayPauseButton.setOnClickListener(listener);
+
+            mVolumeControl = (LinearLayout) LayoutInflater.from(context).inflate(
+                    R.layout.mr_volume_control, mControlView);
+            mVolumeSlider = (SeekBar) mVolumeControl.findViewById(R.id.mr_volume_slider);
+            mVolumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+                private final Runnable mStopTrackingTouch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (mVolumeSliderTouched) {
+                            mVolumeSliderTouched = false;
+                            updateVolumeControl();
+                        }
+                    }
+                };
+
+                @Override
+                public void onStartTrackingTouch(SeekBar seekBar) {
+                    if (mVolumeSliderTouched) {
+                        mVolumeSlider.removeCallbacks(mStopTrackingTouch);
+                    } else {
+                        mVolumeSliderTouched = true;
+                    }
+                }
+
+                @Override
+                public void onStopTrackingTouch(SeekBar seekBar) {
+                    // Defer resetting mVolumeSliderTouched to allow the media route provider
+                    // a little time to settle into its new state and publish the final
+                    // volume update.
+                    mVolumeSlider.postDelayed(mStopTrackingTouch, VOLUME_UPDATE_DELAY_MILLIS);
+                }
+
+                @Override
+                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                    if (fromUser) {
+                        mRoute.requestSetVolume(progress);
+                    }
+                }
+            });
+
+            TypedArray styledAttributes = context.obtainStyledAttributes(new int[] {
+                    R.attr.mediaRouteExpandGroupDrawable,
+                    R.attr.mediaRouteCollapseGroupDrawable
+            });
+            final Drawable expandGroupDrawable = styledAttributes.getDrawable(0);
+            final Drawable collapseGroupDrawable = styledAttributes.getDrawable(1);
+            styledAttributes.recycle();
+
+            mGroupExpandCollapseButton = (ImageButton) mVolumeControl.findViewById(
+                    R.id.mr_group_expand_collapse);
+            mGroupExpandCollapseButton.setOnClickListener(new View.OnClickListener() {
+                private boolean mIsExpanded;
+
+                @Override
+                public void onClick(View v) {
+                    mIsExpanded = !mIsExpanded;
+                    if (mIsExpanded) {
+                        mGroupExpandCollapseButton.setImageDrawable(collapseGroupDrawable);
+                        mVolumeGroupList.setVisibility(View.VISIBLE);
+                        mVolumeGroupList.setAdapter(
+                                new VolumeGroupAdapter(getContext(), getGroup().getRoutes()));
+                    } else {
+                        mGroupExpandCollapseButton.setImageDrawable(expandGroupDrawable);
+                        mVolumeGroupList.setVisibility(View.GONE);
+                    }
+                }
+            });
+        }
+
+        @Override
+        public View getView(final int position, View convertView, ViewGroup parent) {
+            return mItemViews.get(position);
+        }
+
+        public void updateVolumeControl() {
+            if (!mVolumeSliderTouched) {
+                if (isVolumeControlAvailable()) {
+                    if (!mItemViews.contains(mVolumeControl)) {
+                        mItemViews.add(mVolumeControl);
+
+                        notifyDataSetChanged();
+                    }
+                    mVolumeSlider.setMax(mRoute.getVolumeMax());
+                    mVolumeSlider.setProgress(mRoute.getVolume());
+                    if (USE_GROUP) {
+                        if (getGroup() == null) {
+                            mGroupExpandCollapseButton.setVisibility(View.GONE);
+                        } else {
+                            mGroupExpandCollapseButton.setVisibility(View.VISIBLE);
+                            VolumeGroupAdapter adapter =
+                                    (VolumeGroupAdapter) mVolumeGroupList.getAdapter();
+                            if (adapter != null) {
+                                adapter.notifyDataSetChanged();
+                            }
+                        }
+                    }
+                } else if (mItemViews.contains(mVolumeControl)) {
+                    mItemViews.remove(mVolumeControl);
+                    notifyDataSetChanged();
+                }
+            }
+        }
+
+        public void updatePlaybackControl() {
+            if (mCustomControlView == null) {
+                if (!mItemViews.contains(mPlaybackControl)) {
+                    mItemViews.add(0, mPlaybackControl);
+                    notifyDataSetChanged();
+                }
+                CharSequence title = mDescription == null ? null : mDescription.getTitle();
+                boolean hasTitle = !TextUtils.isEmpty(title);
+
+                CharSequence subtitle = mDescription == null ? null : mDescription.getSubtitle();
+                boolean hasSubtitle = !TextUtils.isEmpty(subtitle);
+
+                if (!hasTitle && !hasSubtitle) {
+                    mTitleView.setText(R.string.mr_controller_no_info_available);
+                    mTitleView.setEnabled(false);
+                    mTitleView.setVisibility(View.VISIBLE);
+                    mSubtitleView.setVisibility(View.GONE);
+                } else {
+                    mTitleView.setText(title);
+                    mTitleView.setEnabled(hasTitle);
+                    mTitleView.setVisibility(hasTitle ? View.VISIBLE : View.GONE);
+                    mSubtitleView.setText(subtitle);
+                    mSubtitleView.setVisibility(hasSubtitle ? View.VISIBLE : View.GONE);
+                }
+                if (mState != null) {
+                    boolean isPlaying = mState.getState() == PlaybackStateCompat.STATE_BUFFERING
+                            || mState.getState() == PlaybackStateCompat.STATE_PLAYING;
+                    boolean supportsPlay = (mState.getActions() & (PlaybackStateCompat.ACTION_PLAY
+                            | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
+                    boolean supportsPause = (mState.getActions() & (PlaybackStateCompat.ACTION_PAUSE
+                            | PlaybackStateCompat.ACTION_PLAY_PAUSE)) != 0;
+                    if (isPlaying && supportsPause) {
+                        mPlayPauseButton.setVisibility(View.VISIBLE);
+                        mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
+                                getContext(), R.attr.mediaRoutePauseDrawable));
+                        mPlayPauseButton.setContentDescription(getContext().getResources()
+                                .getText(R.string.mr_controller_pause));
+                    } else if (!isPlaying && supportsPlay) {
+                        mPlayPauseButton.setVisibility(View.VISIBLE);
+                        mPlayPauseButton.setImageResource(MediaRouterThemeHelper.getThemeResource(
+                                getContext(), R.attr.mediaRoutePlayDrawable));
+                        mPlayPauseButton.setContentDescription(getContext().getResources()
+                                .getText(R.string.mr_controller_play));
+                    } else {
+                        mPlayPauseButton.setVisibility(View.GONE);
+                    }
+                }
+            } else if (mItemViews.contains(mPlaybackControl)) {
+                mItemViews.remove(mPlaybackControl);
+                notifyDataSetChanged();
+            }
+        }
+    }
+
     private class VolumeGroupAdapter extends ArrayAdapter<MediaRouter.RouteInfo> {
         final static float DISABLED_ALPHA = .3f;
 
@@ -658,11 +695,11 @@
             if (route != null) {
                 boolean isEnabled = route.isEnabled();
 
-                TextView routeName = (TextView) v.findViewById(R.id.media_route_name);
+                TextView routeName = (TextView) v.findViewById(R.id.mr_name);
                 routeName.setEnabled(isEnabled);
                 routeName.setText(route.getName());
 
-                SeekBar volumeSlider = (SeekBar) v.findViewById(R.id.media_route_volume_slider);
+                SeekBar volumeSlider = (SeekBar) v.findViewById(R.id.mr_volume_slider);
                 volumeSlider.setEnabled(isEnabled);
                 volumeSlider.setTag(position);
                 if (isEnabled) {
@@ -683,7 +720,7 @@
                 // }
 
                 ImageView volumeItemIcon =
-                        (ImageView) v.findViewById(R.id.media_route_volume_item_icon);
+                        (ImageView) v.findViewById(R.id.mr_volume_item_icon);
                 volumeItemIcon.setAlpha(isEnabled ? 255 : (int)(255 * DISABLED_ALPHA));
             }
             return v;