diff options
author | RoboErik <epastern@google.com> | 2014-03-12 22:14:50 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-03-12 22:14:50 +0000 |
commit | 4224e836428391f77adaa14180ad558d12851208 (patch) | |
tree | 80d9b9dbf9968ca3af4fe58a3c160e63ecb7290b /services | |
parent | 361fd3d2ff302d60a49ae2d2d1cc61cb5fdb0ece (diff) | |
parent | 8ae0f34db936a649ddaf9cdd086c224f6514efeb (diff) | |
download | frameworks_base-4224e836428391f77adaa14180ad558d12851208.zip frameworks_base-4224e836428391f77adaa14180ad558d12851208.tar.gz frameworks_base-4224e836428391f77adaa14180ad558d12851208.tar.bz2 |
Merge "Adds a TransportController and TransportPerformer to session"
Diffstat (limited to 'services')
-rw-r--r-- | services/core/java/com/android/server/media/MediaSessionRecord.java | 357 | ||||
-rw-r--r-- | services/core/java/com/android/server/media/MediaSessionService.java | 6 |
2 files changed, 313 insertions, 50 deletions
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 89acec9..1ff925c 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -21,14 +21,22 @@ import android.media.session.IMediaController; import android.media.session.IMediaControllerCallback; import android.media.session.IMediaSession; import android.media.session.IMediaSessionCallback; -import android.media.RemoteControlClient; +import android.media.session.MediaMetadata; +import android.media.session.PlaybackState; +import android.media.Rating; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; +import android.os.Message; import android.os.RemoteException; +import android.os.ResultReceiver; import android.util.Log; +import android.util.Slog; import android.view.KeyEvent; import java.util.ArrayList; +import java.util.List; /** * This is the system implementation of a Session. Apps will interact with the @@ -37,6 +45,8 @@ import java.util.ArrayList; public class MediaSessionRecord implements IBinder.DeathRecipient { private static final String TAG = "MediaSessionImpl"; + private final MessageHandler mHandler; + private final int mPid; private final String mPackageName; private final String mTag; @@ -45,13 +55,25 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { private final SessionCb mSessionCb; private final MediaSessionService mService; - private final ArrayList<IMediaControllerCallback> mSessionCallbacks = + private final Object mControllerLock = new Object(); + private final ArrayList<IMediaControllerCallback> mControllerCallbacks = new ArrayList<IMediaControllerCallback>(); + private final ArrayList<String> mInterfaces = new ArrayList<String>(); + + private boolean mTransportPerformerEnabled = false; + private Bundle mRoute; + + // TransportPerformer fields - private int mPlaybackState = RemoteControlClient.PLAYSTATE_NONE; + private MediaMetadata mMetadata; + private PlaybackState mPlaybackState; + private int mRatingType; + // End TransportPerformer fields + + private boolean mIsPublished = false; public MediaSessionRecord(int pid, String packageName, IMediaSessionCallback cb, String tag, - MediaSessionService service) { + MediaSessionService service, Handler handler) { mPid = pid; mPackageName = packageName; mTag = tag; @@ -59,6 +81,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { mSession = new SessionStub(); mSessionCb = new SessionCb(cb); mService = service; + mHandler = new MessageHandler(handler.getLooper()); } public IMediaSession getSessionBinder() { @@ -69,61 +92,132 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { return mController; } - public void setPlaybackStateInternal(int state) { - mPlaybackState = state; - for (int i = mSessionCallbacks.size() - 1; i >= 0; i--) { - IMediaControllerCallback cb = mSessionCallbacks.get(i); - try { - cb.onPlaybackUpdate(state); - } catch (RemoteException e) { - Log.d(TAG, "SessionCallback object dead in setPlaybackState.", e); - mSessionCallbacks.remove(i); - } - } - } - @Override public void binderDied() { mService.sessionDied(this); } + public boolean isPublished() { + return mIsPublished; + } + private void onDestroy() { mService.destroySession(this); } - private final class SessionStub extends IMediaSession.Stub { + private void pushPlaybackStateUpdate() { + synchronized (mControllerLock) { + for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { + IMediaControllerCallback cb = mControllerCallbacks.get(i); + try { + cb.onPlaybackStateChanged(mPlaybackState); + } catch (RemoteException e) { + Log.w(TAG, "Removing dead callback in pushPlaybackStateUpdate.", e); + mControllerCallbacks.remove(i); + } + } + } + } - @Override - public void setPlaybackState(int state) throws RemoteException { - setPlaybackStateInternal(state); + private void pushMetadataUpdate() { + synchronized (mControllerLock) { + for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { + IMediaControllerCallback cb = mControllerCallbacks.get(i); + try { + cb.onMetadataChanged(mMetadata); + } catch (RemoteException e) { + Log.w(TAG, "Removing dead callback in pushMetadataUpdate.", e); + mControllerCallbacks.remove(i); + } + } } + } + + private void pushRouteUpdate() { + synchronized (mControllerLock) { + for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { + IMediaControllerCallback cb = mControllerCallbacks.get(i); + try { + cb.onRouteChanged(mRoute); + } catch (RemoteException e) { + Log.w(TAG, "Removing dead callback in pushRouteUpdate.", e); + mControllerCallbacks.remove(i); + } + } + } + } + + private void pushEvent(String event, Bundle data) { + synchronized (mControllerLock) { + for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) { + IMediaControllerCallback cb = mControllerCallbacks.get(i); + try { + cb.onEvent(event, data); + } catch (RemoteException e) { + Log.w(TAG, "Removing dead callback in pushRouteUpdate.", e); + mControllerCallbacks.remove(i); + } + } + } + } + + private final class SessionStub extends IMediaSession.Stub { @Override - public void destroy() throws RemoteException { + public void destroy() { onDestroy(); } @Override - public void sendEvent(Bundle data) throws RemoteException { + public void sendEvent(String event, Bundle data) { + mHandler.post(MessageHandler.MSG_SEND_EVENT, event, data); } @Override - public IMediaController getMediaSessionToken() throws RemoteException { + public IMediaController getMediaController() { return mController; } @Override - public void setMetadata(Bundle metadata) throws RemoteException { + public void setRouteState(Bundle routeState) { + } + + @Override + public void setRoute(Bundle mediaRouteDescriptor) { + mRoute = mediaRouteDescriptor; + mHandler.post(MessageHandler.MSG_UPDATE_ROUTE); + } + + @Override + public void publish() { + mIsPublished = true; // TODO push update to service + } + @Override + public void setTransportPerformerEnabled() { + mTransportPerformerEnabled = true; } @Override - public void setRouteState(Bundle routeState) throws RemoteException { + public List<String> getSupportedInterfaces() { + return mInterfaces; } @Override - public void setRoute(Bundle medaiRouteDescriptor) throws RemoteException { + public void setMetadata(MediaMetadata metadata) { + mMetadata = metadata; + mHandler.post(MessageHandler.MSG_UPDATE_METADATA); } + @Override + public void setPlaybackState(PlaybackState state) { + mPlaybackState = state; + mHandler.post(MessageHandler.MSG_UPDATE_PLAYBACK_STATE); + } + + @Override + public void setRatingType(int type) { + mRatingType = type; + } } class SessionCb { @@ -139,32 +233,96 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { try { mCb.onMediaButton(mediaButtonIntent); } catch (RemoteException e) { - Log.d(TAG, "Controller object dead in sendMediaRequest.", e); - onDestroy(); + Slog.e(TAG, "Remote failure in sendMediaRequest.", e); + } + } + + public void sendCommand(String command, Bundle extras, ResultReceiver cb) { + try { + mCb.onCommand(command, extras, cb); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in sendCommand.", e); + } + } + + public void play() { + try { + mCb.onPlay(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in play.", e); } } - public void sendCommand(String command, Bundle extras) { + public void pause() { try { - mCb.onCommand(command, extras); + mCb.onPause(); } catch (RemoteException e) { - Log.d(TAG, "Controller object dead in sendCommand.", e); - onDestroy(); + Slog.e(TAG, "Remote failure in pause.", e); } } - public void registerCallbackListener(IMediaSessionCallback cb) { + public void stop() { + try { + mCb.onStop(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in stop.", e); + } + } + public void next() { + try { + mCb.onNext(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in next.", e); + } } + public void previous() { + try { + mCb.onPrevious(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in previous.", e); + } + } + + public void fastForward() { + try { + mCb.onFastForward(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in fastForward.", e); + } + } + + public void rewind() { + try { + mCb.onRewind(); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in rewind.", e); + } + } + + public void seekTo(long pos) { + try { + mCb.onSeekTo(pos); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in seekTo.", e); + } + } + + public void rate(Rating rating) { + try { + mCb.onRate(rating); + } catch (RemoteException e) { + Slog.e(TAG, "Remote failure in rate.", e); + } + } } class ControllerStub extends IMediaController.Stub { - /* - */ @Override - public void sendCommand(String command, Bundle extras) throws RemoteException { - mSessionCb.sendCommand(command, extras); + public void sendCommand(String command, Bundle extras, ResultReceiver cb) + throws RemoteException { + mSessionCb.sendCommand(command, extras, cb); } @Override @@ -172,29 +330,130 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { mSessionCb.sendMediaButton(mediaButtonIntent); } - /* - */ @Override - public void registerCallbackListener(IMediaControllerCallback cb) throws RemoteException { - if (!mSessionCallbacks.contains(cb)) { - mSessionCallbacks.add(cb); + public void registerCallbackListener(IMediaControllerCallback cb) { + synchronized (mControllerLock) { + if (!mControllerCallbacks.contains(cb)) { + mControllerCallbacks.add(cb); + } } } - /* - */ @Override public void unregisterCallbackListener(IMediaControllerCallback cb) throws RemoteException { - mSessionCallbacks.remove(cb); + synchronized (mControllerLock) { + mControllerCallbacks.remove(cb); + } } - /* - */ @Override - public int getPlaybackState() throws RemoteException { + public void play() throws RemoteException { + mSessionCb.play(); + } + + @Override + public void pause() throws RemoteException { + mSessionCb.pause(); + } + + @Override + public void stop() throws RemoteException { + mSessionCb.stop(); + } + + @Override + public void next() throws RemoteException { + mSessionCb.next(); + } + + @Override + public void previous() throws RemoteException { + mSessionCb.previous(); + } + + @Override + public void fastForward() throws RemoteException { + mSessionCb.fastForward(); + } + + @Override + public void rewind() throws RemoteException { + mSessionCb.rewind(); + } + + @Override + public void seekTo(long pos) throws RemoteException { + mSessionCb.seekTo(pos); + } + + @Override + public void rate(Rating rating) throws RemoteException { + mSessionCb.rate(rating); + } + + + @Override + public MediaMetadata getMetadata() { + return mMetadata; + } + + @Override + public PlaybackState getPlaybackState() { return mPlaybackState; } + + @Override + public int getRatingType() { + return mRatingType; + } + + @Override + public boolean isTransportControlEnabled() throws RemoteException { + return mTransportPerformerEnabled; + } + } + + private class MessageHandler extends Handler { + private static final int MSG_UPDATE_METADATA = 1; + private static final int MSG_UPDATE_PLAYBACK_STATE = 2; + private static final int MSG_UPDATE_ROUTE = 3; + private static final int MSG_SEND_EVENT = 4; + + public MessageHandler(Looper looper) { + super(looper); + } + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_UPDATE_METADATA: + pushMetadataUpdate(); + break; + case MSG_UPDATE_PLAYBACK_STATE: + pushPlaybackStateUpdate(); + break; + case MSG_UPDATE_ROUTE: + pushRouteUpdate(); + break; + case MSG_SEND_EVENT: + pushEvent((String) msg.obj, msg.getData()); + break; + } + } + + public void post(int what) { + post(what, null); + } + + public void post(int what, Object obj) { + obtainMessage(what, obj).sendToTarget(); + } + + public void post(int what, Object obj, Bundle data) { + Message msg = obtainMessage(what, obj); + msg.setData(data); + msg.sendToTarget(); + } } } diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index a7ff926..8fe6055 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -21,6 +21,7 @@ import android.media.session.IMediaSession; import android.media.session.IMediaSessionCallback; import android.media.session.IMediaSessionManager; import android.os.Binder; +import android.os.Handler; import android.os.RemoteException; import android.text.TextUtils; import android.util.Log; @@ -41,6 +42,8 @@ public class MediaSessionService extends SystemService { private final ArrayList<MediaSessionRecord> mSessions = new ArrayList<MediaSessionRecord>(); private final Object mLock = new Object(); + // TODO do we want a separate thread for handling mediasession messages? + private final Handler mHandler = new Handler(); public MediaSessionService(Context context) { super(context); @@ -91,7 +94,8 @@ public class MediaSessionService extends SystemService { private MediaSessionRecord createSessionLocked(int pid, String packageName, IMediaSessionCallback cb, String tag) { - final MediaSessionRecord session = new MediaSessionRecord(pid, packageName, cb, tag, this); + final MediaSessionRecord session = new MediaSessionRecord(pid, packageName, cb, tag, this, + mHandler); try { cb.asBinder().linkToDeath(session, 0); } catch (RemoteException e) { |