Skip to content

Commit 1b4dc0f

Browse files
adampAndroid (Google) Code Review
authored andcommitted
Merge "Volume control in MediaRouter dialogs" into jb-dev
2 parents 706a869 + 4599696 commit 1b4dc0f

File tree

4 files changed

+162
-47
lines changed

4 files changed

+162
-47
lines changed

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11582,6 +11582,7 @@ package android.media {
1158211582
}
1158311583

1158411584
public static class MediaRouter.UserRouteInfo extends android.media.MediaRouter.RouteInfo {
11585+
method public android.media.RemoteControlClient getRemoteControlClient();
1158511586
method public void setIconDrawable(android.graphics.drawable.Drawable);
1158611587
method public void setIconResource(int);
1158711588
method public void setName(java.lang.CharSequence);

core/java/com/android/internal/app/MediaRouteChooserDialogFragment.java

Lines changed: 141 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,16 @@
2525
import android.app.MediaRouteButton;
2626
import android.content.Context;
2727
import android.graphics.drawable.Drawable;
28+
import android.media.AudioManager;
2829
import android.media.MediaRouter;
2930
import android.media.MediaRouter.RouteCategory;
3031
import android.media.MediaRouter.RouteGroup;
3132
import android.media.MediaRouter.RouteInfo;
33+
import android.media.MediaRouter.UserRouteInfo;
34+
import android.media.RemoteControlClient;
3235
import android.os.Bundle;
3336
import android.text.TextUtils;
37+
import android.view.KeyEvent;
3438
import android.view.LayoutInflater;
3539
import android.view.View;
3640
import android.view.ViewGroup;
@@ -41,6 +45,7 @@
4145
import android.widget.ImageButton;
4246
import android.widget.ImageView;
4347
import android.widget.ListView;
48+
import android.widget.SeekBar;
4449
import android.widget.TextView;
4550

4651
import java.util.ArrayList;
@@ -67,15 +72,20 @@ public class MediaRouteChooserDialogFragment extends DialogFragment {
6772
};
6873

6974
MediaRouter mRouter;
75+
AudioManager mAudio;
7076
private int mRouteTypes;
7177

7278
private LayoutInflater mInflater;
7379
private LauncherListener mLauncherListener;
7480
private View.OnClickListener mExtendedSettingsListener;
7581
private RouteAdapter mAdapter;
7682
private ListView mListView;
83+
private SeekBar mVolumeSlider;
84+
private ImageView mVolumeIcon;
7785

7886
final RouteComparator mComparator = new RouteComparator();
87+
final MediaRouterCallback mCallback = new MediaRouterCallback();
88+
private boolean mIgnoreVolumeChanges;
7989

8090
public MediaRouteChooserDialogFragment() {
8191
setStyle(STYLE_NO_TITLE, R.style.Theme_DeviceDefault_Dialog);
@@ -89,6 +99,7 @@ public void setLauncherListener(LauncherListener listener) {
8999
public void onAttach(Activity activity) {
90100
super.onAttach(activity);
91101
mRouter = (MediaRouter) activity.getSystemService(Context.MEDIA_ROUTER_SERVICE);
102+
mAudio = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
92103
}
93104

94105
@Override
@@ -98,20 +109,13 @@ public void onDetach() {
98109
mLauncherListener.onDetached(this);
99110
}
100111
if (mAdapter != null) {
101-
mRouter.removeCallback(mAdapter.mCallback);
102112
mAdapter = null;
103113
}
104114
mInflater = null;
115+
mRouter.removeCallback(mCallback);
105116
mRouter = null;
106117
}
107118

108-
/**
109-
* Implemented by the MediaRouteButton that launched this dialog
110-
*/
111-
public interface LauncherListener {
112-
public void onDetached(MediaRouteChooserDialogFragment detachedFragment);
113-
}
114-
115119
public void setExtendedSettingsClickListener(View.OnClickListener listener) {
116120
mExtendedSettingsListener = listener;
117121
}
@@ -120,14 +124,70 @@ public void setRouteTypes(int types) {
120124
mRouteTypes = types;
121125
}
122126

127+
void updateVolume() {
128+
final RouteInfo selectedRoute = mRouter.getSelectedRoute(mRouteTypes);
129+
final boolean defaultAudioSelected = selectedRoute == mRouter.getSystemAudioRoute();
130+
final boolean selectedSystemRoute =
131+
selectedRoute.getCategory() == mRouter.getSystemAudioCategory();
132+
mVolumeIcon.setImageResource(defaultAudioSelected ?
133+
R.drawable.ic_audio_vol : R.drawable.ic_media_route_on_holo_dark);
134+
135+
mIgnoreVolumeChanges = true;
136+
mVolumeSlider.setEnabled(true);
137+
if (selectedSystemRoute) {
138+
// Use the standard media audio stream
139+
mVolumeSlider.setMax(mAudio.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
140+
mVolumeSlider.setProgress(mAudio.getStreamVolume(AudioManager.STREAM_MUSIC));
141+
} else {
142+
final RouteInfo firstSelected;
143+
if (selectedRoute instanceof RouteGroup) {
144+
firstSelected = ((RouteGroup) selectedRoute).getRouteAt(0);
145+
} else {
146+
firstSelected = selectedRoute;
147+
}
148+
149+
RemoteControlClient rcc = null;
150+
if (firstSelected instanceof UserRouteInfo) {
151+
rcc = ((UserRouteInfo) firstSelected).getRemoteControlClient();
152+
}
153+
154+
if (rcc == null) {
155+
// No RemoteControlClient? Assume volume can't be controlled.
156+
// Disable the slider and show it at max volume.
157+
mVolumeSlider.setMax(1);
158+
mVolumeSlider.setProgress(1);
159+
mVolumeSlider.setEnabled(false);
160+
} else {
161+
// TODO: Connect this to the remote control volume
162+
}
163+
}
164+
mIgnoreVolumeChanges = false;
165+
}
166+
167+
void changeVolume(int newValue) {
168+
if (mIgnoreVolumeChanges) return;
169+
170+
RouteCategory selectedCategory = mRouter.getSelectedRoute(mRouteTypes).getCategory();
171+
if (selectedCategory == mRouter.getSystemAudioCategory()) {
172+
final int maxVolume = mAudio.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
173+
newValue = Math.max(0, Math.min(newValue, maxVolume));
174+
mAudio.setStreamVolume(AudioManager.STREAM_MUSIC, newValue, 0);
175+
}
176+
}
177+
123178
@Override
124179
public View onCreateView(LayoutInflater inflater, ViewGroup container,
125180
Bundle savedInstanceState) {
126181
mInflater = inflater;
127182
final View layout = inflater.inflate(R.layout.media_route_chooser_layout, container, false);
128-
final View extendedSettingsButton = layout.findViewById(R.id.extended_settings);
183+
184+
mVolumeIcon = (ImageView) layout.findViewById(R.id.volume_icon);
185+
mVolumeSlider = (SeekBar) layout.findViewById(R.id.volume_slider);
186+
updateVolume();
187+
mVolumeSlider.setOnSeekBarChangeListener(new VolumeSliderChangeListener());
129188

130189
if (mExtendedSettingsListener != null) {
190+
final View extendedSettingsButton = layout.findViewById(R.id.extended_settings);
131191
extendedSettingsButton.setVisibility(View.VISIBLE);
132192
extendedSettingsButton.setOnClickListener(mExtendedSettingsListener);
133193
}
@@ -138,7 +198,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container,
138198
list.setOnItemClickListener(mAdapter);
139199

140200
mListView = list;
141-
mRouter.addCallback(mRouteTypes, mAdapter.mCallback);
201+
mRouter.addCallback(mRouteTypes, mCallback);
142202

143203
mAdapter.scrollToSelectedItem();
144204

@@ -174,7 +234,6 @@ private class RouteAdapter extends BaseAdapter implements ListView.OnItemClickLi
174234

175235
private int mSelectedItemPosition = -1;
176236
private final ArrayList<Object> mItems = new ArrayList<Object>();
177-
final MediaRouterCallback mCallback = new MediaRouterCallback();
178237

179238
private RouteCategory mCategoryEditingGroups;
180239
private RouteGroup mEditingGroup;
@@ -443,10 +502,6 @@ void bindHeaderView(int position, ViewHolder holder) {
443502
holder.text1.setText(cat.getName(getActivity()));
444503
}
445504

446-
public int getSelectedRoutePosition() {
447-
return mSelectedItemPosition;
448-
}
449-
450505
@Override
451506
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
452507
final int type = getItemViewType(position);
@@ -523,46 +578,49 @@ public void onClick(View v) {
523578
scrollToEditingGroup();
524579
}
525580
}
581+
}
526582

527-
class MediaRouterCallback extends MediaRouter.Callback {
528-
@Override
529-
public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
530-
update();
531-
}
583+
class MediaRouterCallback extends MediaRouter.Callback {
584+
@Override
585+
public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
586+
mAdapter.update();
587+
updateVolume();
588+
}
532589

533-
@Override
534-
public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
535-
update();
536-
}
590+
@Override
591+
public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
592+
mAdapter.update();
593+
}
537594

538-
@Override
539-
public void onRouteAdded(MediaRouter router, RouteInfo info) {
540-
update();
541-
}
595+
@Override
596+
public void onRouteAdded(MediaRouter router, RouteInfo info) {
597+
mAdapter.update();
598+
updateVolume();
599+
}
542600

543-
@Override
544-
public void onRouteRemoved(MediaRouter router, RouteInfo info) {
545-
if (info == mEditingGroup) {
546-
finishGrouping();
547-
}
548-
update();
601+
@Override
602+
public void onRouteRemoved(MediaRouter router, RouteInfo info) {
603+
if (info == mAdapter.mEditingGroup) {
604+
mAdapter.finishGrouping();
549605
}
606+
mAdapter.update();
607+
updateVolume();
608+
}
550609

551-
@Override
552-
public void onRouteChanged(MediaRouter router, RouteInfo info) {
553-
notifyDataSetChanged();
554-
}
610+
@Override
611+
public void onRouteChanged(MediaRouter router, RouteInfo info) {
612+
mAdapter.notifyDataSetChanged();
613+
}
555614

556-
@Override
557-
public void onRouteGrouped(MediaRouter router, RouteInfo info,
558-
RouteGroup group, int index) {
559-
update();
560-
}
615+
@Override
616+
public void onRouteGrouped(MediaRouter router, RouteInfo info,
617+
RouteGroup group, int index) {
618+
mAdapter.update();
619+
}
561620

562-
@Override
563-
public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
564-
update();
565-
}
621+
@Override
622+
public void onRouteUngrouped(MediaRouter router, RouteInfo info, RouteGroup group) {
623+
mAdapter.update();
566624
}
567625
}
568626

@@ -587,5 +645,41 @@ public void onBackPressed() {
587645
super.onBackPressed();
588646
}
589647
}
648+
649+
public boolean onKeyDown(int keyCode, KeyEvent event) {
650+
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN && mVolumeSlider.isEnabled()) {
651+
mVolumeSlider.incrementProgressBy(-1);
652+
return true;
653+
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mVolumeSlider.isEnabled()) {
654+
mVolumeSlider.incrementProgressBy(1);
655+
return true;
656+
} else {
657+
return super.onKeyDown(keyCode, event);
658+
}
659+
}
660+
}
661+
662+
/**
663+
* Implemented by the MediaRouteButton that launched this dialog
664+
*/
665+
public interface LauncherListener {
666+
public void onDetached(MediaRouteChooserDialogFragment detachedFragment);
667+
}
668+
669+
class VolumeSliderChangeListener implements SeekBar.OnSeekBarChangeListener {
670+
671+
@Override
672+
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
673+
changeVolume(progress);
674+
}
675+
676+
@Override
677+
public void onStartTrackingTouch(SeekBar seekBar) {
678+
}
679+
680+
@Override
681+
public void onStopTrackingTouch(SeekBar seekBar) {
682+
}
683+
590684
}
591685
}

core/res/res/values/public.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,9 @@
11681168
<java-symbol type="attr" name="externalRouteEnabledDrawable" />
11691169
<java-symbol type="id" name="extended_settings" />
11701170
<java-symbol type="id" name="check" />
1171+
<java-symbol type="id" name="volume_slider" />
1172+
<java-symbol type="id" name="volume_icon" />
1173+
<java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
11711174
<java-symbol type="layout" name="media_route_chooser_layout" />
11721175
<java-symbol type="layout" name="media_route_list_item_top_header" />
11731176
<java-symbol type="layout" name="media_route_list_item_section_header" />

media/java/android/media/MediaRouter.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,13 @@ public RouteInfo getSystemAudioRoute() {
197197
return sStatic.mDefaultAudio;
198198
}
199199

200+
/**
201+
* @hide for use by framework routing UI
202+
*/
203+
public RouteCategory getSystemAudioCategory() {
204+
return sStatic.mSystemCategory;
205+
}
206+
200207
/**
201208
* Return the currently selected route for the given types
202209
*
@@ -739,6 +746,16 @@ public void setRemoteControlClient(RemoteControlClient rcc) {
739746
mRcc = rcc;
740747
}
741748

749+
/**
750+
* Retrieve the RemoteControlClient associated with this route, if one has been set.
751+
*
752+
* @return the RemoteControlClient associated with this route
753+
* @see #setRemoteControlClient(RemoteControlClient)
754+
*/
755+
public RemoteControlClient getRemoteControlClient() {
756+
return mRcc;
757+
}
758+
742759
/**
743760
* Set an icon that will be used to represent this route.
744761
* The system may use this icon in picker UIs or similar.

0 commit comments

Comments
 (0)