diff options
author | RoboErik <epastern@google.com> | 2014-06-03 16:49:49 -0700 |
---|---|---|
committer | RoboErik <epastern@google.com> | 2014-06-08 12:18:25 -0700 |
commit | 5d3114b64a88ac1f72becd8d46f148c666f64aa3 (patch) | |
tree | d450bb5c980612e4517a05fab22359d559bd9095 /media | |
parent | 2386bd5de40849bd312482e33105070cf438011d (diff) | |
download | frameworks_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.java | 161 | ||||
-rw-r--r-- | media/java/android/media/session/MediaSession.java | 44 | ||||
-rw-r--r-- | media/java/android/media/session/RemoteVolumeProvider.java | 15 |
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 |