summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorRoboErik <epastern@google.com>2014-06-03 16:49:49 -0700
committerRoboErik <epastern@google.com>2014-06-08 12:18:25 -0700
commit5d3114b64a88ac1f72becd8d46f148c666f64aa3 (patch)
treed450bb5c980612e4517a05fab22359d559bd9095 /media
parent2386bd5de40849bd312482e33105070cf438011d (diff)
downloadframeworks_base-5d3114b64a88ac1f72becd8d46f148c666f64aa3.zip
frameworks_base-5d3114b64a88ac1f72becd8d46f148c666f64aa3.tar.gz
frameworks_base-5d3114b64a88ac1f72becd8d46f148c666f64aa3.tar.bz2
b/15388389 Add volume handling support to MediaRouter
This makes MediaRouter work with sessions to handle volume requests. Should work with all existing custom volume handling. Change-Id: I5dfde26a6203a1072b7fc700978b4ca852ebe7d0
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/MediaRouter.java161
-rw-r--r--media/java/android/media/session/MediaSession.java44
-rw-r--r--media/java/android/media/session/RemoteVolumeProvider.java15
3 files changed, 178 insertions, 42 deletions
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index a4d491d8..1da0215 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -28,6 +28,8 @@ import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
+import android.media.session.MediaSession;
+import android.media.session.RemoteVolumeProvider;
import android.os.Handler;
import android.os.IBinder;
import android.os.Process;
@@ -58,6 +60,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
public class MediaRouter {
private static final String TAG = "MediaRouter";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean USE_SESSIONS = true;
static class Static implements DisplayManager.DisplayListener {
final Context mAppContext;
@@ -1141,7 +1144,7 @@ public class MediaRouter {
public RouteCategory createRouteCategory(CharSequence name, boolean isGroupable) {
return new RouteCategory(name, ROUTE_TYPE_USER, isGroupable);
}
-
+
/**
* Create a new route category. Each route must belong to a category.
*
@@ -1980,6 +1983,7 @@ public class MediaRouter {
*/
public static class UserRouteInfo extends RouteInfo {
RemoteControlClient mRcc;
+ SessionVolumeProvider mSvp;
UserRouteInfo(RouteCategory category) {
super(category);
@@ -1996,7 +2000,7 @@ public class MediaRouter {
mName = name;
routeUpdated();
}
-
+
/**
* Set the user-visible name of this route.
* <p>
@@ -2100,7 +2104,11 @@ public class MediaRouter {
public void setPlaybackType(int type) {
if (mPlaybackType != type) {
mPlaybackType = type;
- setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, type);
+ if (USE_SESSIONS) {
+ configureSessionVolume();
+ } else {
+ setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, type);
+ }
}
}
@@ -2113,8 +2121,12 @@ public class MediaRouter {
public void setVolumeHandling(int volumeHandling) {
if (mVolumeHandling != volumeHandling) {
mVolumeHandling = volumeHandling;
- setPlaybackInfoOnRcc(
- RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, volumeHandling);
+ if (USE_SESSIONS) {
+ configureSessionVolume();
+ } else {
+ setPlaybackInfoOnRcc(
+ RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, volumeHandling);
+ }
}
}
@@ -2127,7 +2139,13 @@ public class MediaRouter {
volume = Math.max(0, Math.min(volume, getVolumeMax()));
if (mVolume != volume) {
mVolume = volume;
- setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME, volume);
+ if (USE_SESSIONS) {
+ if (mSvp != null) {
+ mSvp.notifyVolumeChanged();
+ }
+ } else {
+ setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME, volume);
+ }
dispatchRouteVolumeChanged(this);
if (mGroup != null) {
mGroup.memberVolumeChanged(this);
@@ -2166,7 +2184,11 @@ public class MediaRouter {
public void setVolumeMax(int volumeMax) {
if (mVolumeMax != volumeMax) {
mVolumeMax = volumeMax;
- setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, volumeMax);
+ if (USE_SESSIONS) {
+ configureSessionVolume();
+ } else {
+ setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, volumeMax);
+ }
}
}
@@ -2177,29 +2199,76 @@ public class MediaRouter {
public void setPlaybackStream(int stream) {
if (mPlaybackStream != stream) {
mPlaybackStream = stream;
- setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_USES_STREAM, stream);
+ if (USE_SESSIONS) {
+ configureSessionVolume();
+ } else {
+ setPlaybackInfoOnRcc(RemoteControlClient.PLAYBACKINFO_USES_STREAM, stream);
+ }
}
}
private void updatePlaybackInfoOnRcc() {
- if ((mRcc != null) && (mRcc.getRcseId() != RemoteControlClient.RCSE_ID_UNREGISTERED)) {
- mRcc.setPlaybackInformation(
- RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, mVolumeMax);
- mRcc.setPlaybackInformation(
- RemoteControlClient.PLAYBACKINFO_VOLUME, mVolume);
- mRcc.setPlaybackInformation(
- RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, mVolumeHandling);
- mRcc.setPlaybackInformation(
- RemoteControlClient.PLAYBACKINFO_USES_STREAM, mPlaybackStream);
- mRcc.setPlaybackInformation(
- RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, mPlaybackType);
- // let AudioService know whom to call when remote volume needs to be updated
- try {
- sStatic.mAudioService.registerRemoteVolumeObserverForRcc(
- mRcc.getRcseId() /* rccId */, mRemoteVolObserver /* rvo */);
- } catch (RemoteException e) {
- Log.e(TAG, "Error registering remote volume observer", e);
+ if (USE_SESSIONS) {
+ configureSessionVolume();
+ } else {
+ if ((mRcc != null)
+ && (mRcc.getRcseId() != RemoteControlClient.RCSE_ID_UNREGISTERED)) {
+ mRcc.setPlaybackInformation(
+ RemoteControlClient.PLAYBACKINFO_VOLUME_MAX, mVolumeMax);
+ mRcc.setPlaybackInformation(
+ RemoteControlClient.PLAYBACKINFO_VOLUME, mVolume);
+ mRcc.setPlaybackInformation(
+ RemoteControlClient.PLAYBACKINFO_VOLUME_HANDLING, mVolumeHandling);
+ mRcc.setPlaybackInformation(
+ RemoteControlClient.PLAYBACKINFO_USES_STREAM, mPlaybackStream);
+ mRcc.setPlaybackInformation(
+ RemoteControlClient.PLAYBACKINFO_PLAYBACK_TYPE, mPlaybackType);
+ // let AudioService know whom to call when remote volume
+ // needs to be updated
+ try {
+ sStatic.mAudioService.registerRemoteVolumeObserverForRcc(
+ mRcc.getRcseId() /* rccId */, mRemoteVolObserver /* rvo */);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error registering remote volume observer", e);
+ }
+ }
+ }
+ }
+
+ private void configureSessionVolume() {
+ if (mRcc == null) {
+ if (DEBUG) {
+ Log.d(TAG, "No Rcc to configure volume for route " + mName);
+ }
+ return;
+ }
+ MediaSession session = mRcc.getMediaSession();
+ if (session == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Rcc has no session to configure volume");
+ }
+ return;
+ }
+ if (mPlaybackType == RemoteControlClient.PLAYBACK_TYPE_REMOTE) {
+ int volumeControl = RemoteVolumeProvider.VOLUME_CONTROL_FIXED;
+ switch (mVolumeHandling) {
+ case RemoteControlClient.PLAYBACK_VOLUME_VARIABLE:
+ volumeControl = RemoteVolumeProvider.VOLUME_CONTROL_ABSOLUTE;
+ break;
+ case RemoteControlClient.PLAYBACK_VOLUME_FIXED:
+ default:
+ break;
}
+ // Only register a new listener if necessary
+ if (mSvp == null || mSvp.getVolumeControl() != volumeControl
+ || mSvp.getMaxVolume() != mVolumeMax) {
+ mSvp = new SessionVolumeProvider(volumeControl, mVolumeMax);
+ session.setPlaybackToRemote(mSvp);
+ }
+ } else {
+ // We only know how to handle local and remote, fall back to local if not remote.
+ session.setPlaybackToLocal(mPlaybackStream);
+ mSvp = null;
}
}
@@ -2208,6 +2277,42 @@ public class MediaRouter {
mRcc.setPlaybackInformation(what, value);
}
}
+
+ class SessionVolumeProvider extends RemoteVolumeProvider {
+
+ public SessionVolumeProvider(int volumeControl, int maxVolume) {
+ super(volumeControl, maxVolume);
+ }
+
+ @Override
+ public int onGetCurrentVolume() {
+ return mVcb == null ? 0 : mVcb.route.mVolume;
+ }
+
+ @Override
+ public void onSetVolumeTo(final int volume) {
+ sStatic.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mVcb != null) {
+ mVcb.vcb.onVolumeSetRequest(mVcb.route, volume);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAdjustVolumeBy(final int delta) {
+ sStatic.mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mVcb != null) {
+ mVcb.vcb.onVolumeUpdateRequest(mVcb.route, delta);
+ }
+ }
+ });
+ }
+ }
}
/**
@@ -2504,17 +2609,17 @@ public class MediaRouter {
public CharSequence getName() {
return getName(sStatic.mResources);
}
-
+
/**
* Return the properly localized/configuration dependent name of this RouteCategory.
- *
+ *
* @param context Context to resolve name resources
* @return the name of this route category
*/
public CharSequence getName(Context context) {
return getName(context.getResources());
}
-
+
CharSequence getName(Resources res) {
if (mNameResId != 0) {
return res.getText(mNameResId);
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 7972639..4ba1351 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -277,6 +277,7 @@ public final class MediaSession {
throw new IllegalArgumentException("volumeProvider may not be null!");
}
mVolumeProvider = volumeProvider;
+ volumeProvider.setSession(this);
try {
mBinder.configureVolumeHandling(VOLUME_TYPE_REMOTE, volumeProvider.getVolumeControl(),
@@ -522,6 +523,24 @@ public final class MediaSession {
}
}
+ /**
+ * Notify the system that the remove volume changed.
+ *
+ * @param provider The provider that is handling volume changes.
+ * @hide
+ */
+ void notifyRemoteVolumeChanged(RemoteVolumeProvider provider) {
+ if (provider == null || provider != mVolumeProvider) {
+ Log.w(TAG, "Received update from stale volume provider");
+ return;
+ }
+ try {
+ mBinder.setCurrentVolume(provider.onGetCurrentVolume());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in notifyVolumeChanged", e);
+ }
+ }
+
private void dispatchPlay() {
postToTransportCallbacks(TransportMessageHandler.MSG_PLAY);
}
@@ -963,27 +982,26 @@ public final class MediaSession {
@Override
public void onRouteStateChange(int state) throws RemoteException {
// TODO
-
}
- /*
- * (non-Javadoc)
- * @see android.media.session.ISessionCallback#onAdjustVolumeBy(int)
- */
@Override
public void onAdjustVolumeBy(int delta) throws RemoteException {
- // TODO(epastern): Auto-generated method stub
-
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ if (session.mVolumeProvider != null) {
+ session.mVolumeProvider.onAdjustVolumeBy(delta);
+ }
+ }
}
- /*
- * (non-Javadoc)
- * @see android.media.session.ISessionCallback#onSetVolumeTo(int)
- */
@Override
public void onSetVolumeTo(int value) throws RemoteException {
- // TODO(epastern): Auto-generated method stub
-
+ MediaSession session = mMediaSession.get();
+ if (session != null) {
+ if (session.mVolumeProvider != null) {
+ session.mVolumeProvider.onSetVolumeTo(value);
+ }
+ }
}
}
diff --git a/media/java/android/media/session/RemoteVolumeProvider.java b/media/java/android/media/session/RemoteVolumeProvider.java
index 47f672f..606b1d7 100644
--- a/media/java/android/media/session/RemoteVolumeProvider.java
+++ b/media/java/android/media/session/RemoteVolumeProvider.java
@@ -15,6 +15,9 @@
*/
package android.media.session;
+import android.os.RemoteException;
+import android.util.Log;
+
/**
* Handles requests to adjust or set the volume on a session. This is also used
* to push volume updates back to the session after a request has been handled.
@@ -22,6 +25,7 @@ package android.media.session;
* {@link MediaSession#setPlaybackToRemote}.
*/
public abstract class RemoteVolumeProvider {
+ private static final String TAG = "RemoteVolumeProvider";
/**
* The volume is fixed and can not be modified. Requests to change volume
@@ -46,6 +50,8 @@ public abstract class RemoteVolumeProvider {
private final int mControlType;
private final int mMaxVolume;
+ private MediaSession mSession;
+
/**
* Create a new volume provider for handling volume events. You must specify
* the type of volume control and the maximum volume that can be used.
@@ -88,7 +94,7 @@ public abstract class RemoteVolumeProvider {
* Notify the system that the remote playback's volume has been changed.
*/
public final void notifyVolumeChanged() {
- // TODO
+ mSession.notifyRemoteVolumeChanged(this);
}
/**
@@ -107,4 +113,11 @@ public abstract class RemoteVolumeProvider {
*/
public void onAdjustVolumeBy(int delta) {
}
+
+ /**
+ * @hide
+ */
+ void setSession(MediaSession session) {
+ mSession = session;
+ }
} \ No newline at end of file