summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorRoboErik <epastern@google.com>2014-03-12 22:14:50 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-03-12 22:14:50 +0000
commit4224e836428391f77adaa14180ad558d12851208 (patch)
tree80d9b9dbf9968ca3af4fe58a3c160e63ecb7290b /services
parent361fd3d2ff302d60a49ae2d2d1cc61cb5fdb0ece (diff)
parent8ae0f34db936a649ddaf9cdd086c224f6514efeb (diff)
downloadframeworks_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.java357
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java6
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) {