From 79fa4630bbca7c6c251eea99fe8997e4b45becee Mon Sep 17 00:00:00 2001 From: RoboErik Date: Tue, 27 May 2014 16:49:09 -0700 Subject: API changes to sessions Changes requested by API Council review. A second CL will refactor TransportController and TransportPerformer based on feedback. Change-Id: Ie26a7d01d7021232a66c2edf1eb58120437fdfde --- api/current.txt | 100 +++++++--------- media/java/android/media/MediaMetadata.java | 11 ++ media/java/android/media/RemoteControlClient.java | 4 +- .../android/media/session/ISessionController.aidl | 2 +- .../android/media/session/MediaController.java | 29 ++--- media/java/android/media/session/MediaSession.java | 52 ++++---- .../android/media/session/MediaSessionInfo.java | 2 + .../media/session/MediaSessionLegacyHelper.java | 22 ++-- .../android/media/session/MediaSessionManager.java | 1 + .../android/media/session/MediaSessionToken.java | 7 +- .../java/android/media/session/PlaybackState.java | 132 ++++++++++----------- .../media/session/RemoteVolumeProvider.java | 37 ++++-- .../android/media/session/TransportController.java | 6 +- .../android/media/session/TransportPerformer.java | 117 +++++++++--------- .../android/server/media/MediaSessionRecord.java | 36 +++--- .../android/server/media/MediaSessionStack.java | 14 +-- .../com/android/onemedia/OnePlayerActivity.java | 20 ++-- .../src/com/android/onemedia/PlayerService.java | 6 +- .../src/com/android/onemedia/PlayerSession.java | 30 ++--- .../onemedia/provider/OneMediaRouteProvider.java | 16 +-- 20 files changed, 334 insertions(+), 310 deletions(-) diff --git a/api/current.txt b/api/current.txt index df908e0..acf6e87 100644 --- a/api/current.txt +++ b/api/current.txt @@ -14583,6 +14583,7 @@ package android.media { method public long getLong(java.lang.String); method public android.media.Rating getRating(java.lang.String); method public java.lang.String getString(java.lang.String); + method public java.util.Set keySet(); method public int size(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -15720,16 +15721,16 @@ package android.media.session { public final class MediaController { method public void addCallback(android.media.session.MediaController.Callback); method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler); + method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public static android.media.session.MediaController fromToken(android.media.session.MediaSessionToken); method public android.media.session.TransportController getTransportController(); method public void removeCallback(android.media.session.MediaController.Callback); - method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); - method public void sendMediaButton(int); + method public void sendControlCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); } public static abstract class MediaController.Callback { ctor public MediaController.Callback(); - method public void onEvent(java.lang.String, android.os.Bundle); + method public void onSessionEvent(java.lang.String, android.os.Bundle); } public final class MediaSession { @@ -15740,36 +15741,27 @@ package android.media.session { method public boolean isActive(); method public void release(); method public void removeCallback(android.media.session.MediaSession.Callback); - method public void sendEvent(java.lang.String, android.os.Bundle); + method public void sendSessionEvent(java.lang.String, android.os.Bundle); method public void setActive(boolean); method public void setFlags(int); method public void setLaunchPendingIntent(android.app.PendingIntent); - method public void useLocalPlayback(int); - method public void useRemotePlayback(android.media.session.RemoteVolumeProvider); + method public void setPlaybackToLocal(int); + method public void setPlaybackToRemote(android.media.session.RemoteVolumeProvider); field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2 } public static abstract class MediaSession.Callback { ctor public MediaSession.Callback(); - method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); - method public void onMediaButton(android.content.Intent); - } - - public final class MediaSessionInfo implements android.os.Parcelable { - method public int describeContents(); - method public java.lang.String getId(); - method public java.lang.String getPackageName(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator CREATOR; + method public void onControlCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); + method public void onMediaButtonEvent(android.content.Intent); } public final class MediaSessionManager { method public android.media.session.MediaSession createSession(java.lang.String); - method public java.util.List getActiveSessions(android.content.ComponentName); } - public class MediaSessionToken implements android.os.Parcelable { + public final class MediaSessionToken implements android.os.Parcelable { method public int describeContents(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -15781,49 +15773,50 @@ package android.media.session { method public int describeContents(); method public long getActions(); method public long getBufferPosition(); - method public java.lang.String getErrorMessage(); + method public java.lang.CharSequence getErrorMessage(); + method public float getPlaybackRate(); method public long getPosition(); - method public float getRate(); method public int getState(); method public void setActions(long); method public void setBufferPosition(long); - method public void setErrorMessage(java.lang.String); + method public void setErrorMessage(java.lang.CharSequence); method public void setState(int, long, float); method public void writeToParcel(android.os.Parcel, int); - field public static final long ACTION_FASTFORWARD = 64L; // 0x40L - field public static final long ACTION_NEXT_ITEM = 32L; // 0x20L + field public static final long ACTION_FAST_FORWARD = 64L; // 0x40L field public static final long ACTION_PAUSE = 2L; // 0x2L field public static final long ACTION_PLAY = 4L; // 0x4L field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L - field public static final long ACTION_PREVIOUS_ITEM = 16L; // 0x10L - field public static final long ACTION_RATING = 128L; // 0x80L field public static final long ACTION_REWIND = 8L; // 0x8L field public static final long ACTION_SEEK_TO = 256L; // 0x100L + field public static final long ACTION_SET_RATING = 128L; // 0x80L + field public static final long ACTION_SKIP_TO_NEXT = 32L; // 0x20L + field public static final long ACTION_SKIP_TO_PREVIOUS = 16L; // 0x10L field public static final long ACTION_STOP = 1L; // 0x1L field public static final android.os.Parcelable.Creator CREATOR; field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL - field public static final int PLAYSTATE_BUFFERING = 6; // 0x6 - field public static final int PLAYSTATE_ERROR = 7; // 0x7 - field public static final int PLAYSTATE_FAST_FORWARDING = 4; // 0x4 - field public static final int PLAYSTATE_NONE = 0; // 0x0 - field public static final int PLAYSTATE_PAUSED = 2; // 0x2 - field public static final int PLAYSTATE_PLAYING = 3; // 0x3 - field public static final int PLAYSTATE_REWINDING = 5; // 0x5 - field public static final int PLAYSTATE_SKIPPING_BACKWARDS = 9; // 0x9 - field public static final int PLAYSTATE_SKIPPING_FORWARDS = 10; // 0xa - field public static final int PLAYSTATE_STOPPED = 1; // 0x1 + field public static final int STATE_BUFFERING = 6; // 0x6 + field public static final int STATE_ERROR = 7; // 0x7 + field public static final int STATE_FAST_FORWARDING = 4; // 0x4 + field public static final int STATE_NONE = 0; // 0x0 + field public static final int STATE_PAUSED = 2; // 0x2 + field public static final int STATE_PLAYING = 3; // 0x3 + field public static final int STATE_REWINDING = 5; // 0x5 + field public static final int STATE_SKIPPING_TO_NEXT = 10; // 0xa + field public static final int STATE_SKIPPING_TO_PREVIOUS = 9; // 0x9 + field public static final int STATE_STOPPED = 1; // 0x1 } public abstract class RemoteVolumeProvider { ctor public RemoteVolumeProvider(int, int); - method public abstract int getCurrentVolume(); method public final int getFlags(); method public final int getMaxVolume(); method public final void notifyVolumeChanged(); - method public void onAdjustVolume(int); - method public void onSetVolume(int); - field public static final int FLAG_VOLUME_ABSOLUTE = 2; // 0x2 - field public static final int FLAG_VOLUME_RELATIVE = 1; // 0x1 + method public void onAdjustVolumeBy(int); + method public abstract int onGetCurrentVolume(); + method public void onSetVolumeTo(int); + field public static final int VOLUME_CONTROL_ABSOLUTE = 4; // 0x4 + field public static final int VOLUME_CONTROL_FIXED = 1; // 0x1 + field public static final int VOLUME_CONTROL_RELATIVE = 2; // 0x2 } public final class TransportController { @@ -15833,14 +15826,14 @@ package android.media.session { method public android.media.MediaMetadata getMetadata(); method public android.media.session.PlaybackState getPlaybackState(); method public int getRatingType(); - method public void next(); method public void pause(); method public void play(); - method public void previous(); - method public void rate(android.media.Rating); method public void removeStateListener(android.media.session.TransportController.TransportStateListener); method public void rewind(); method public void seekTo(long); + method public void setRating(android.media.Rating); + method public void skipToNext(); + method public void skipToPrevious(); method public void stop(); } @@ -15851,24 +15844,23 @@ package android.media.session { } public final class TransportPerformer { - method public void addListener(android.media.session.TransportPerformer.Listener); - method public void addListener(android.media.session.TransportPerformer.Listener, android.os.Handler); - method public void removeListener(android.media.session.TransportPerformer.Listener); - method public final void setMetadata(android.media.MediaMetadata); - method public final void setPlaybackState(android.media.session.PlaybackState); + method public void addCallback(android.media.session.TransportPerformer.Callback); + method public void addCallback(android.media.session.TransportPerformer.Callback, android.os.Handler); + method public void removeCallback(android.media.session.TransportPerformer.Callback); + method public void setMetadata(android.media.MediaMetadata); + method public void setPlaybackState(android.media.session.PlaybackState); } - public static abstract class TransportPerformer.Listener { - ctor public TransportPerformer.Listener(); + public static abstract class TransportPerformer.Callback { + ctor public TransportPerformer.Callback(); method public void onFastForward(); - method public void onNext(); method public void onPause(); method public void onPlay(); - method public void onPrevious(); - method public void onRate(android.media.Rating); method public void onRewind(); - method public void onRouteFocusChange(int); method public void onSeekTo(long); + method public void onSetRating(android.media.Rating); + method public void onSkipToNext(); + method public void onSkipToPrevious(); method public void onStop(); } diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java index ff73a10..5dc8e1b 100644 --- a/media/java/android/media/MediaMetadata.java +++ b/media/java/android/media/MediaMetadata.java @@ -23,6 +23,8 @@ import android.util.ArrayMap; import android.util.Log; import android.util.SparseArray; +import java.util.Set; + /** * Contains metadata about an item, such as the title, artist, etc. */ @@ -301,6 +303,15 @@ public final class MediaMetadata implements Parcelable { } /** + * Returns a Set containing the Strings used as keys in this metadata. + * + * @return a Set of String keys + */ + public Set keySet() { + return mBundle.keySet(); + } + + /** * Helper for getting the String key used by {@link MediaMetadata} from the * integer key that {@link MediaMetadataEditor} uses. * diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java index 26ae3cc..b89affd 100644 --- a/media/java/android/media/RemoteControlClient.java +++ b/media/java/android/media/RemoteControlClient.java @@ -1317,7 +1317,7 @@ public class RemoteControlClient } // USE_SESSIONS - private TransportPerformer.Listener mTransportListener = new TransportPerformer.Listener() { + private TransportPerformer.Callback mTransportListener = new TransportPerformer.Callback() { @Override public void onSeekTo(long pos) { @@ -1325,7 +1325,7 @@ public class RemoteControlClient } @Override - public void onRate(Rating rating) { + public void onSetRating(Rating rating) { if ((mTransportControlFlags & FLAG_KEY_MEDIA_RATING) != 0) { if (mEventHandler != null) { mEventHandler.sendMessage(mEventHandler.obtainMessage( diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl index 5ddb6db..9ce0692 100644 --- a/media/java/android/media/session/ISessionController.aidl +++ b/media/java/android/media/session/ISessionController.aidl @@ -30,7 +30,7 @@ import android.view.KeyEvent; */ interface ISessionController { void sendCommand(String command, in Bundle extras, in ResultReceiver cb); - void sendMediaButton(in KeyEvent mediaButton); + boolean sendMediaButton(in KeyEvent mediaButton); void registerCallbackListener(in ISessionControllerCallback cb); void unregisterCallbackListener(in ISessionControllerCallback cb); boolean isTransportControlEnabled(); diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index 642ac2f..63c0839 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -103,24 +103,25 @@ public final class MediaController { } /** - * Send the specified media button to the session. Only media keys can be - * sent using this method. + * Send the specified media button event to the session. Only media keys can + * be sent by this method, other keys will be ignored. * - * @param keycode The media button keycode, such as - * {@link KeyEvent#KEYCODE_MEDIA_PLAY}. + * @param keyEvent The media button event to dispatch. + * @return true if the event was sent to the session, false otherwise. */ - public void sendMediaButton(int keycode) { - if (!KeyEvent.isMediaKey(keycode)) { - throw new IllegalArgumentException("May only send media buttons through " - + "sendMediaButton"); + public boolean dispatchMediaButtonEvent(KeyEvent keyEvent) { + if (keyEvent == null) { + throw new IllegalArgumentException("KeyEvent may not be null"); + } + if (!KeyEvent.isMediaKey(keyEvent.getKeyCode())) { + return false; } - // TODO do something better than key down/up events - KeyEvent event = new KeyEvent(KeyEvent.ACTION_UP, keycode); try { - mSessionBinder.sendMediaButton(event); + return mSessionBinder.sendMediaButton(keyEvent); } catch (RemoteException e) { Log.d(TAG, "Dead object in sendMediaButton", e); } + return false; } /** @@ -171,7 +172,7 @@ public final class MediaController { * @param params Any parameters to include with the command * @param cb The callback to receive the result on */ - public void sendCommand(String command, Bundle params, ResultReceiver cb) { + public void sendControlCommand(String command, Bundle params, ResultReceiver cb) { if (TextUtils.isEmpty(command)) { throw new IllegalArgumentException("command cannot be null or empty"); } @@ -282,7 +283,7 @@ public final class MediaController { * * @param event */ - public void onEvent(String event, Bundle extras) { + public void onSessionEvent(String event, Bundle extras) { } /** @@ -354,7 +355,7 @@ public final class MediaController { public void handleMessage(Message msg) { switch (msg.what) { case MSG_EVENT: - mCallback.onEvent((String) msg.obj, msg.getData()); + mCallback.onSessionEvent((String) msg.obj, msg.getData()); break; case MSG_ROUTE: mCallback.onRouteChanged((RouteInfo) msg.obj); diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 539dc3c..51dcee1 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -49,12 +49,8 @@ import java.util.List; *

* A MediaSession is created by calling * {@link MediaSessionManager#createSession(String)}. Once a session is created - * apps that have the MEDIA_CONTENT_CONTROL permission can interact with the - * session through - * {@link MediaSessionManager#getActiveSessions(android.content.ComponentName)}. - * The owner of the session may also use {@link #getSessionToken()} to allow - * apps without this permission to create a {@link MediaController} to interact - * with this session. + * the owner of the session may use {@link #getSessionToken()} to allow apps to + * create a {@link MediaController} to interact with this session. *

* To receive commands, media keys, and other events a Callback must be set with * {@link #addCallback(Callback)}. @@ -166,7 +162,9 @@ public final class MediaSession { } /** - * Set the callback to receive updates on. + * Add a callback to receive updates on for the MediaSession. This includes + * media button and volume events. The caller's thread will be used to post + * events. * * @param callback The callback object */ @@ -246,7 +244,7 @@ public final class MediaSession { /** * Set the stream this session is playing on. This will affect the system's - * volume handling for this session. If {@link #useRemotePlayback} was + * volume handling for this session. If {@link #setPlaybackToRemote} was * previously called it will stop receiving volume commands and the system * will begin sending volume changes to the appropriate stream. *

@@ -254,21 +252,21 @@ public final class MediaSession { * * @param stream The {@link AudioManager} stream this session is playing on. */ - public void useLocalPlayback(int stream) { + public void setPlaybackToLocal(int stream) { // TODO } /** * Configure this session to use remote volume handling. This must be called * to receive volume button events, otherwise the system will adjust the - * current stream volume for this session. If {@link #useLocalPlayback} was - * previously called that stream will stop receiving volume changes for this - * session. + * current stream volume for this session. If {@link #setPlaybackToLocal} + * was previously called that stream will stop receiving volume changes for + * this session. * * @param volumeProvider The provider that will handle volume changes. May * not be null. */ - public void useRemotePlayback(RemoteVolumeProvider volumeProvider) { + public void setPlaybackToRemote(RemoteVolumeProvider volumeProvider) { if (volumeProvider == null) { throw new IllegalArgumentException("volumeProvider may not be null!"); } @@ -312,7 +310,7 @@ public final class MediaSession { * @param event The name of the event to send * @param extras Any extras included with the event */ - public void sendEvent(String event, Bundle extras) { + public void sendSessionEvent(String event, Bundle extras) { if (TextUtils.isEmpty(event)) { throw new IllegalArgumentException("event cannot be null or empty"); } @@ -525,7 +523,7 @@ public final class MediaSession { * @param mediaButtonIntent an intent containing the KeyEvent as an * extra */ - public void onMediaButton(Intent mediaButtonIntent) { + public void onMediaButtonEvent(Intent mediaButtonIntent) { } /** @@ -536,7 +534,7 @@ public final class MediaSession { * @param command * @param extras optional */ - public void onCommand(String command, Bundle extras, ResultReceiver cb) { + public void onControlCommand(String command, Bundle extras, ResultReceiver cb) { } /** @@ -645,7 +643,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onPlay(); + tp.dispatchPlay(); } } } @@ -656,7 +654,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onPause(); + tp.dispatchPause(); } } } @@ -667,7 +665,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onStop(); + tp.dispatchStop(); } } } @@ -678,7 +676,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onNext(); + tp.dispatchNext(); } } } @@ -689,7 +687,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onPrevious(); + tp.dispatchPrevious(); } } } @@ -700,7 +698,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onFastForward(); + tp.dispatchFastForward(); } } } @@ -711,7 +709,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onRewind(); + tp.dispatchRewind(); } } } @@ -722,7 +720,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onSeekTo(pos); + tp.dispatchSeekTo(pos); } } } @@ -733,7 +731,7 @@ public final class MediaSession { if (session != null) { TransportPerformer tp = session.getTransportPerformer(); if (tp != null) { - tp.onRate(rating); + tp.dispatchRate(rating); } } } @@ -776,11 +774,11 @@ public final class MediaSession { } switch (msg.what) { case MSG_MEDIA_BUTTON: - mCallback.onMediaButton((Intent) msg.obj); + mCallback.onMediaButtonEvent((Intent) msg.obj); break; case MSG_COMMAND: Command cmd = (Command) msg.obj; - mCallback.onCommand(cmd.command, cmd.extras, cmd.stub); + mCallback.onControlCommand(cmd.command, cmd.extras, cmd.stub); break; case MSG_ROUTE_CHANGE: mCallback.onRequestRouteChange((RouteInfo) msg.obj); diff --git a/media/java/android/media/session/MediaSessionInfo.java b/media/java/android/media/session/MediaSessionInfo.java index 3d8d33f..f701211 100644 --- a/media/java/android/media/session/MediaSessionInfo.java +++ b/media/java/android/media/session/MediaSessionInfo.java @@ -20,6 +20,8 @@ import android.os.Parcelable; /** * Information about a media session, including the owner's package name. + * + * @hide */ public final class MediaSessionInfo implements Parcelable { private final String mId; diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java index 249b9c4..bdf3628 100644 --- a/media/java/android/media/session/MediaSessionLegacyHelper.java +++ b/media/java/android/media/session/MediaSessionLegacyHelper.java @@ -76,7 +76,7 @@ public class MediaSessionLegacyHelper { } } - public void addRccListener(PendingIntent pi, TransportPerformer.Listener listener) { + public void addRccListener(PendingIntent pi, TransportPerformer.Callback listener) { if (pi == null) { Log.w(TAG, "Pending intent was null, can't add rcc listener."); return; @@ -92,9 +92,9 @@ public class MediaSessionLegacyHelper { return; } // Otherwise it changed so we need to switch to the new one - performer.removeListener(holder.mRccListener); + performer.removeCallback(holder.mRccListener); } - performer.addListener(listener, mHandler); + performer.addCallback(listener, mHandler); holder.mRccListener = listener; holder.mFlags |= MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS; holder.mSession.setFlags(holder.mFlags); @@ -110,7 +110,7 @@ public class MediaSessionLegacyHelper { } SessionHolder holder = getHolder(pi, false); if (holder != null && holder.mRccListener != null) { - holder.mSession.getTransportPerformer().removeListener(holder.mRccListener); + holder.mSession.getTransportPerformer().removeCallback(holder.mRccListener); holder.mRccListener = null; holder.mFlags &= ~MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS; holder.mSession.setFlags(holder.mFlags); @@ -141,7 +141,7 @@ public class MediaSessionLegacyHelper { // set this flag holder.mFlags |= MediaSession.FLAG_HANDLES_MEDIA_BUTTONS; holder.mSession.setFlags(holder.mFlags); - holder.mSession.getTransportPerformer().addListener(holder.mMediaButtonListener, mHandler); + holder.mSession.getTransportPerformer().addCallback(holder.mMediaButtonListener, mHandler); holder.mMediaButtonReceiver = new MediaButtonReceiver(pi, context); holder.mSession.addCallback(holder.mMediaButtonReceiver, mHandler); @@ -156,7 +156,7 @@ public class MediaSessionLegacyHelper { } SessionHolder holder = getHolder(pi, false); if (holder != null && holder.mMediaButtonListener != null) { - holder.mSession.getTransportPerformer().removeListener(holder.mMediaButtonListener); + holder.mSession.getTransportPerformer().removeCallback(holder.mMediaButtonListener); holder.mFlags &= ~MediaSession.FLAG_HANDLES_MEDIA_BUTTONS; holder.mSession.setFlags(holder.mFlags); holder.mMediaButtonListener = null; @@ -201,12 +201,12 @@ public class MediaSessionLegacyHelper { } @Override - public void onMediaButton(Intent mediaButtonIntent) { + public void onMediaButtonEvent(Intent mediaButtonIntent) { MediaSessionLegacyHelper.sendKeyEvent(mPendingIntent, mContext, mediaButtonIntent); } } - private static final class MediaButtonListener extends TransportPerformer.Listener { + private static final class MediaButtonListener extends TransportPerformer.Callback { private final PendingIntent mPendingIntent; private final Context mContext; @@ -226,12 +226,12 @@ public class MediaSessionLegacyHelper { } @Override - public void onNext() { + public void onSkipToNext() { sendKeyEvent(KeyEvent.KEYCODE_MEDIA_NEXT); } @Override - public void onPrevious() { + public void onSkipToPrevious() { sendKeyEvent(KeyEvent.KEYCODE_MEDIA_PREVIOUS); } @@ -272,7 +272,7 @@ public class MediaSessionLegacyHelper { public final PendingIntent mPi; public MediaButtonListener mMediaButtonListener; public MediaButtonReceiver mMediaButtonReceiver; - public TransportPerformer.Listener mRccListener; + public TransportPerformer.Callback mRccListener; public int mFlags; public SessionHolder(MediaSession session, PendingIntent pi) { diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java index 0589a7d..8d5e338 100644 --- a/media/java/android/media/session/MediaSessionManager.java +++ b/media/java/android/media/session/MediaSessionManager.java @@ -106,6 +106,7 @@ public final class MediaSessionManager { * @param notificationListener The enabled notification listener component. * May be null. * @return A list of controllers for ongoing sessions + * @hide */ public List getActiveSessions(ComponentName notificationListener) { return getActiveSessionsForUser(notificationListener, UserHandle.myUserId()); diff --git a/media/java/android/media/session/MediaSessionToken.java b/media/java/android/media/session/MediaSessionToken.java index f5569a4..86f5662 100644 --- a/media/java/android/media/session/MediaSessionToken.java +++ b/media/java/android/media/session/MediaSessionToken.java @@ -20,7 +20,12 @@ import android.media.session.ISessionController; import android.os.Parcel; import android.os.Parcelable; -public class MediaSessionToken implements Parcelable { +/** + * Represents an ongoing session. This may be passed to apps by the session + * owner to allow them to create a {@link MediaController} to communicate with + * the session. + */ +public final class MediaSessionToken implements Parcelable { private ISessionController mBinder; /** diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java index 7ef38eaa..e09ac3f 100644 --- a/media/java/android/media/session/PlaybackState.java +++ b/media/java/android/media/session/PlaybackState.java @@ -22,7 +22,7 @@ import android.os.SystemClock; /** * Playback state for a {@link MediaSession}. This includes a state like - * {@link PlaybackState#PLAYSTATE_PLAYING}, the current playback position, + * {@link PlaybackState#STATE_PLAYING}, the current playback position, * and the current control capabilities. */ public final class PlaybackState implements Parcelable { @@ -59,28 +59,28 @@ public final class PlaybackState implements Parcelable { * * @see #setActions */ - public static final long ACTION_PREVIOUS_ITEM = 1 << 4; + public static final long ACTION_SKIP_TO_PREVIOUS = 1 << 4; /** * Indicates this performer supports the next command. * * @see #setActions */ - public static final long ACTION_NEXT_ITEM = 1 << 5; + public static final long ACTION_SKIP_TO_NEXT = 1 << 5; /** * Indicates this performer supports the fast forward command. * * @see #setActions */ - public static final long ACTION_FASTFORWARD = 1 << 6; + public static final long ACTION_FAST_FORWARD = 1 << 6; /** * Indicates this performer supports the set rating command. * * @see #setActions */ - public static final long ACTION_RATING = 1 << 7; + public static final long ACTION_SET_RATING = 1 << 7; /** * Indicates this performer supports the seek to command. @@ -102,42 +102,42 @@ public final class PlaybackState implements Parcelable { * * @see #setState */ - public final static int PLAYSTATE_NONE = 0; + public final static int STATE_NONE = 0; /** * State indicating this item is currently stopped. * * @see #setState */ - public final static int PLAYSTATE_STOPPED = 1; + public final static int STATE_STOPPED = 1; /** * State indicating this item is currently paused. * * @see #setState */ - public final static int PLAYSTATE_PAUSED = 2; + public final static int STATE_PAUSED = 2; /** * State indicating this item is currently playing. * * @see #setState */ - public final static int PLAYSTATE_PLAYING = 3; + public final static int STATE_PLAYING = 3; /** * State indicating this item is currently fast forwarding. * * @see #setState */ - public final static int PLAYSTATE_FAST_FORWARDING = 4; + public final static int STATE_FAST_FORWARDING = 4; /** * State indicating this item is currently rewinding. * * @see #setState */ - public final static int PLAYSTATE_REWINDING = 5; + public final static int STATE_REWINDING = 5; /** * State indicating this item is currently buffering and will begin playing @@ -145,7 +145,7 @@ public final class PlaybackState implements Parcelable { * * @see #setState */ - public final static int PLAYSTATE_BUFFERING = 6; + public final static int STATE_BUFFERING = 6; /** * State indicating this item is currently in an error state. The error @@ -153,30 +153,30 @@ public final class PlaybackState implements Parcelable { * * @see #setState */ - public final static int PLAYSTATE_ERROR = 7; + public final static int STATE_ERROR = 7; /** * State indicating the class doing playback is currently connecting to a * route. Depending on the implementation you may return to the previous - * state when the connection finishes or enter {@link #PLAYSTATE_NONE}. If - * the connection failed {@link #PLAYSTATE_ERROR} should be used. + * state when the connection finishes or enter {@link #STATE_NONE}. If + * the connection failed {@link #STATE_ERROR} should be used. * @hide */ - public final static int PLAYSTATE_CONNECTING = 8; + public final static int STATE_CONNECTING = 8; /** * State indicating the player is currently skipping to the previous item. * * @see #setState */ - public final static int PLAYSTATE_SKIPPING_BACKWARDS = 9; + public final static int STATE_SKIPPING_TO_PREVIOUS = 9; /** * State indicating the player is currently skipping to the next item. * * @see #setState */ - public final static int PLAYSTATE_SKIPPING_FORWARDS = 10; + public final static int STATE_SKIPPING_TO_NEXT = 10; /** * Use this value for the position to indicate the position is not known. @@ -188,7 +188,7 @@ public final class PlaybackState implements Parcelable { private long mBufferPosition; private float mRate; private long mActions; - private String mErrorMessage; + private CharSequence mErrorMessage; private long mUpdateTime; /** @@ -221,7 +221,7 @@ public final class PlaybackState implements Parcelable { mUpdateTime = in.readLong(); mBufferPosition = in.readLong(); mActions = in.readLong(); - mErrorMessage = in.readString(); + mErrorMessage = in.readCharSequence(); } @@ -252,20 +252,20 @@ public final class PlaybackState implements Parcelable { dest.writeLong(mUpdateTime); dest.writeLong(mBufferPosition); dest.writeLong(mActions); - dest.writeString(mErrorMessage); + dest.writeCharSequence(mErrorMessage); } /** * Get the current state of playback. One of the following: *

    - *
  • {@link PlaybackState#PLAYSTATE_NONE}
  • - *
  • {@link PlaybackState#PLAYSTATE_STOPPED}
  • - *
  • {@link PlaybackState#PLAYSTATE_PLAYING}
  • - *
  • {@link PlaybackState#PLAYSTATE_PAUSED}
  • - *
  • {@link PlaybackState#PLAYSTATE_FAST_FORWARDING}
  • - *
  • {@link PlaybackState#PLAYSTATE_REWINDING}
  • - *
  • {@link PlaybackState#PLAYSTATE_BUFFERING}
  • - *
  • {@link PlaybackState#PLAYSTATE_ERROR}
  • + *
  • {@link PlaybackState#STATE_NONE}
  • + *
  • {@link PlaybackState#STATE_STOPPED}
  • + *
  • {@link PlaybackState#STATE_PLAYING}
  • + *
  • {@link PlaybackState#STATE_PAUSED}
  • + *
  • {@link PlaybackState#STATE_FAST_FORWARDING}
  • + *
  • {@link PlaybackState#STATE_REWINDING}
  • + *
  • {@link PlaybackState#STATE_BUFFERING}
  • + *
  • {@link PlaybackState#STATE_ERROR}
  • */ public int getState() { return mState; @@ -283,25 +283,25 @@ public final class PlaybackState implements Parcelable { *

    * The state must be one of the following: *

      - *
    • {@link PlaybackState#PLAYSTATE_NONE}
    • - *
    • {@link PlaybackState#PLAYSTATE_STOPPED}
    • - *
    • {@link PlaybackState#PLAYSTATE_PLAYING}
    • - *
    • {@link PlaybackState#PLAYSTATE_PAUSED}
    • - *
    • {@link PlaybackState#PLAYSTATE_FAST_FORWARDING}
    • - *
    • {@link PlaybackState#PLAYSTATE_REWINDING}
    • - *
    • {@link PlaybackState#PLAYSTATE_BUFFERING}
    • - *
    • {@link PlaybackState#PLAYSTATE_ERROR}
    • + *
    • {@link PlaybackState#STATE_NONE}
    • + *
    • {@link PlaybackState#STATE_STOPPED}
    • + *
    • {@link PlaybackState#STATE_PLAYING}
    • + *
    • {@link PlaybackState#STATE_PAUSED}
    • + *
    • {@link PlaybackState#STATE_FAST_FORWARDING}
    • + *
    • {@link PlaybackState#STATE_REWINDING}
    • + *
    • {@link PlaybackState#STATE_BUFFERING}
    • + *
    • {@link PlaybackState#STATE_ERROR}
    • *
    * * @param state The current state of playback. * @param position The position in the current track in ms. - * @param rate The current rate of playback as a multiple of normal + * @param playbackRate The current rate of playback as a multiple of normal * playback. */ - public void setState(int state, long position, float rate) { + public void setState(int state, long position, float playbackRate) { this.mState = state; this.mPosition = position; - this.mRate = rate; + this.mRate = playbackRate; mUpdateTime = SystemClock.elapsedRealtime(); } @@ -337,7 +337,7 @@ public final class PlaybackState implements Parcelable { * * @return The current rate of playback. */ - public float getRate() { + public float getPlaybackRate() { return mRate; } @@ -345,15 +345,15 @@ public final class PlaybackState implements Parcelable { * Get the current actions available on this session. This should use a * bitmask of the available actions. *
      - *
    • {@link PlaybackState#ACTION_PREVIOUS_ITEM}
    • + *
    • {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}
    • *
    • {@link PlaybackState#ACTION_REWIND}
    • *
    • {@link PlaybackState#ACTION_PLAY}
    • *
    • {@link PlaybackState#ACTION_PAUSE}
    • *
    • {@link PlaybackState#ACTION_STOP}
    • - *
    • {@link PlaybackState#ACTION_FASTFORWARD}
    • - *
    • {@link PlaybackState#ACTION_NEXT_ITEM}
    • + *
    • {@link PlaybackState#ACTION_FAST_FORWARD}
    • + *
    • {@link PlaybackState#ACTION_SKIP_TO_NEXT}
    • *
    • {@link PlaybackState#ACTION_SEEK_TO}
    • - *
    • {@link PlaybackState#ACTION_RATING}
    • + *
    • {@link PlaybackState#ACTION_SET_RATING}
    • *
    */ public long getActions() { @@ -364,15 +364,15 @@ public final class PlaybackState implements Parcelable { * Set the current capabilities available on this session. This should use a * bitmask of the available capabilities. *
      - *
    • {@link PlaybackState#ACTION_PREVIOUS_ITEM}
    • + *
    • {@link PlaybackState#ACTION_SKIP_TO_PREVIOUS}
    • *
    • {@link PlaybackState#ACTION_REWIND}
    • *
    • {@link PlaybackState#ACTION_PLAY}
    • *
    • {@link PlaybackState#ACTION_PAUSE}
    • *
    • {@link PlaybackState#ACTION_STOP}
    • - *
    • {@link PlaybackState#ACTION_FASTFORWARD}
    • - *
    • {@link PlaybackState#ACTION_NEXT_ITEM}
    • + *
    • {@link PlaybackState#ACTION_FAST_FORWARD}
    • + *
    • {@link PlaybackState#ACTION_SKIP_TO_NEXT}
    • *
    • {@link PlaybackState#ACTION_SEEK_TO}
    • - *
    • {@link PlaybackState#ACTION_RATING}
    • + *
    • {@link PlaybackState#ACTION_SET_RATING}
    • *
    */ public void setActions(long capabilities) { @@ -381,9 +381,9 @@ public final class PlaybackState implements Parcelable { /** * Get a user readable error message. This should be set when the state is - * {@link PlaybackState#PLAYSTATE_ERROR}. + * {@link PlaybackState#STATE_ERROR}. */ - public String getErrorMessage() { + public CharSequence getErrorMessage() { return mErrorMessage; } @@ -400,9 +400,9 @@ public final class PlaybackState implements Parcelable { /** * Set a user readable error message. This should be set when the state is - * {@link PlaybackState#PLAYSTATE_ERROR}. + * {@link PlaybackState#STATE_ERROR}. */ - public void setErrorMessage(String errorMessage) { + public void setErrorMessage(CharSequence errorMessage) { mErrorMessage = errorMessage; } @@ -417,23 +417,23 @@ public final class PlaybackState implements Parcelable { public static int getStateFromRccState(int rccState) { switch (rccState) { case RemoteControlClient.PLAYSTATE_BUFFERING: - return PLAYSTATE_BUFFERING; + return STATE_BUFFERING; case RemoteControlClient.PLAYSTATE_ERROR: - return PLAYSTATE_ERROR; + return STATE_ERROR; case RemoteControlClient.PLAYSTATE_FAST_FORWARDING: - return PLAYSTATE_FAST_FORWARDING; + return STATE_FAST_FORWARDING; case RemoteControlClient.PLAYSTATE_NONE: - return PLAYSTATE_NONE; + return STATE_NONE; case RemoteControlClient.PLAYSTATE_PAUSED: - return PLAYSTATE_PAUSED; + return STATE_PAUSED; case RemoteControlClient.PLAYSTATE_PLAYING: - return PLAYSTATE_PLAYING; + return STATE_PLAYING; case RemoteControlClient.PLAYSTATE_REWINDING: - return PLAYSTATE_REWINDING; + return STATE_REWINDING; case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS: - return PLAYSTATE_SKIPPING_BACKWARDS; + return STATE_SKIPPING_TO_PREVIOUS; case RemoteControlClient.PLAYSTATE_STOPPED: - return PLAYSTATE_STOPPED; + return STATE_STOPPED; default: return -1; } @@ -457,7 +457,7 @@ public final class PlaybackState implements Parcelable { private static long getActionForRccFlag(int flag) { switch (flag) { case RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS: - return ACTION_PREVIOUS_ITEM; + return ACTION_SKIP_TO_PREVIOUS; case RemoteControlClient.FLAG_KEY_MEDIA_REWIND: return ACTION_REWIND; case RemoteControlClient.FLAG_KEY_MEDIA_PLAY: @@ -469,13 +469,13 @@ public final class PlaybackState implements Parcelable { case RemoteControlClient.FLAG_KEY_MEDIA_STOP: return ACTION_STOP; case RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD: - return ACTION_FASTFORWARD; + return ACTION_FAST_FORWARD; case RemoteControlClient.FLAG_KEY_MEDIA_NEXT: - return ACTION_NEXT_ITEM; + return ACTION_SKIP_TO_NEXT; case RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE: return ACTION_SEEK_TO; case RemoteControlClient.FLAG_KEY_MEDIA_RATING: - return ACTION_RATING; + return ACTION_SET_RATING; } return 0; } diff --git a/media/java/android/media/session/RemoteVolumeProvider.java b/media/java/android/media/session/RemoteVolumeProvider.java index 9526cc8..2dcf649 100644 --- a/media/java/android/media/session/RemoteVolumeProvider.java +++ b/media/java/android/media/session/RemoteVolumeProvider.java @@ -4,32 +4,43 @@ package android.media.session; * 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. * You can set a volume provider on a session by calling - * {@link MediaSession#useRemotePlayback}. + * {@link MediaSession#setPlaybackToRemote}. */ public abstract class RemoteVolumeProvider { /** - * Handles relative volume changes via {@link #onAdjustVolume(int)}. + * The volume is fixed and can not be modified. Requests to change volume + * should be ignored. */ - public static final int FLAG_VOLUME_RELATIVE = 1 << 0; + public static final int VOLUME_CONTROL_FIXED = 1 << 0; /** - * Handles setting the volume via {@link #onSetVolume(int)}. + * The volume control uses relative adjustment via + * {@link #onAdjustVolumeBy(int)}. Attempts to set the volume to a specific + * value should be ignored. */ - public static final int FLAG_VOLUME_ABSOLUTE = 1 << 1; + public static final int VOLUME_CONTROL_RELATIVE = 1 << 1; + + /** + * The volume control uses an absolute value. It may be adjusted using + * {@link #onAdjustVolumeBy(int)} or set directly using + * {@link #onSetVolumeTo(int)}. + */ + public static final int VOLUME_CONTROL_ABSOLUTE = 1 << 2; private final int mFlags; private final int mMaxVolume; /** * Create a new volume provider for handling volume events. You must specify - * the type of events and the maximum volume that can be used. + * the type of volume control and the maximum volume that can be used. * - * @param flags The flags to use with this provider. + * @param volumeControl The method for controlling volume that is used by + * this provider. * @param maxVolume The maximum allowed volume. */ - public RemoteVolumeProvider(int flags, int maxVolume) { - mFlags = flags; + public RemoteVolumeProvider(int volumeControl, int maxVolume) { + mFlags = volumeControl; mMaxVolume = maxVolume; } @@ -38,7 +49,7 @@ public abstract class RemoteVolumeProvider { * * @return The current volume. */ - public abstract int getCurrentVolume(); + public abstract int onGetCurrentVolume(); /** * Get the flags that were set for this volume provider. @@ -59,7 +70,7 @@ public abstract class RemoteVolumeProvider { } /** - * Notify the system that the remove playback's volume has been changed. + * Notify the system that the remote playback's volume has been changed. */ public final void notifyVolumeChanged() { // TODO @@ -70,7 +81,7 @@ public abstract class RemoteVolumeProvider { * * @param volume The volume to set the output to. */ - public void onSetVolume(int volume) { + public void onSetVolumeTo(int volume) { } /** @@ -79,6 +90,6 @@ public abstract class RemoteVolumeProvider { * * @param delta The amount to change the volume */ - public void onAdjustVolume(int delta) { + public void onAdjustVolumeBy(int delta) { } } \ No newline at end of file diff --git a/media/java/android/media/session/TransportController.java b/media/java/android/media/session/TransportController.java index 090489b..4bd39ff 100644 --- a/media/java/android/media/session/TransportController.java +++ b/media/java/android/media/session/TransportController.java @@ -144,7 +144,7 @@ public final class TransportController { /** * Skip to the next item. */ - public void next() { + public void skipToNext() { try { mBinder.next(); } catch (RemoteException e) { @@ -167,7 +167,7 @@ public final class TransportController { /** * Skip to the previous item. */ - public void previous() { + public void skipToPrevious() { try { mBinder.previous(); } catch (RemoteException e) { @@ -182,7 +182,7 @@ public final class TransportController { * * @param rating The rating to set for the current content */ - public void rate(Rating rating) { + public void setRating(Rating rating) { try { mBinder.rate(rating); } catch (RemoteException e) { diff --git a/media/java/android/media/session/TransportPerformer.java b/media/java/android/media/session/TransportPerformer.java index 1588d8f..9c4c686 100644 --- a/media/java/android/media/session/TransportPerformer.java +++ b/media/java/android/media/session/TransportPerformer.java @@ -33,7 +33,7 @@ import java.util.ArrayList; public final class TransportPerformer { private static final String TAG = "TransportPerformer"; private final Object mLock = new Object(); - private final ArrayList mListeners = new ArrayList(); + private final ArrayList mCallbacks = new ArrayList(); private ISession mBinder; @@ -45,35 +45,35 @@ public final class TransportPerformer { } /** - * Add a listener to receive updates on. + * Add a callback to receive updates on. * - * @param listener The callback object + * @param callback The callback object */ - public void addListener(Listener listener) { - addListener(listener, null); + public void addCallback(Callback callback) { + addCallback(callback, null); } /** - * Add a listener to receive updates on. The updates will be posted to the + * Add a callback to receive updates on. The updates will be posted to the * specified handler. If no handler is provided they will be posted to the * caller's thread. * - * @param listener The listener to receive updates on + * @param callback The callback to receive updates on * @param handler The handler to post the updates on */ - public void addListener(Listener listener, Handler handler) { - if (listener == null) { - throw new IllegalArgumentException("Listener cannot be null"); + public void addCallback(Callback callback, Handler handler) { + if (callback == null) { + throw new IllegalArgumentException("Callback cannot be null"); } synchronized (mLock) { - if (getHandlerForListenerLocked(listener) != null) { - Log.w(TAG, "Listener is already added, ignoring"); + if (getHandlerForCallbackLocked(callback) != null) { + Log.w(TAG, "Callback is already added, ignoring"); } if (handler == null) { handler = new Handler(); } - MessageHandler msgHandler = new MessageHandler(handler.getLooper(), listener); - mListeners.add(msgHandler); + MessageHandler msgHandler = new MessageHandler(handler.getLooper(), callback); + mCallbacks.add(msgHandler); } } @@ -81,14 +81,14 @@ public final class TransportPerformer { * Stop receiving updates on the specified handler. If an update has already * been posted you may still receive it after this call returns. * - * @param listener The listener to stop receiving updates on + * @param callback The callback to stop receiving updates on */ - public void removeListener(Listener listener) { - if (listener == null) { - throw new IllegalArgumentException("Listener cannot be null"); + public void removeCallback(Callback callback) { + if (callback == null) { + throw new IllegalArgumentException("Callback cannot be null"); } synchronized (mLock) { - removeListenerLocked(listener); + removeCallbackLocked(callback); } } @@ -97,7 +97,7 @@ public final class TransportPerformer { * * @param state The current state of playback */ - public final void setPlaybackState(PlaybackState state) { + public void setPlaybackState(PlaybackState state) { try { mBinder.setPlaybackState(state); } catch (RemoteException e) { @@ -111,7 +111,7 @@ public final class TransportPerformer { * * @param metadata The new metadata */ - public final void setMetadata(MediaMetadata metadata) { + public void setMetadata(MediaMetadata metadata) { try { mBinder.setMetadata(metadata); } catch (RemoteException e) { @@ -122,80 +122,80 @@ public final class TransportPerformer { /** * @hide */ - public final void onPlay() { + public void dispatchPlay() { post(MessageHandler.MESSAGE_PLAY); } /** * @hide */ - public final void onPause() { + public void dispatchPause() { post(MessageHandler.MESSAGE_PAUSE); } /** * @hide */ - public final void onStop() { + public void dispatchStop() { post(MessageHandler.MESSAGE_STOP); } /** * @hide */ - public final void onNext() { + public void dispatchNext() { post(MessageHandler.MESSAGE_NEXT); } /** * @hide */ - public final void onPrevious() { + public void dispatchPrevious() { post(MessageHandler.MESSAGE_PREVIOUS); } /** * @hide */ - public final void onFastForward() { + public void dispatchFastForward() { post(MessageHandler.MESSAGE_FAST_FORWARD); } /** * @hide */ - public final void onRewind() { + public void dispatchRewind() { post(MessageHandler.MESSAGE_REWIND); } /** * @hide */ - public final void onSeekTo(long pos) { + public void dispatchSeekTo(long pos) { post(MessageHandler.MESSAGE_SEEK_TO, pos); } /** * @hide */ - public final void onRate(Rating rating) { + public void dispatchRate(Rating rating) { post(MessageHandler.MESSAGE_RATE, rating); } - private MessageHandler getHandlerForListenerLocked(Listener listener) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - MessageHandler handler = mListeners.get(i); - if (listener == handler.mListener) { + private MessageHandler getHandlerForCallbackLocked(Callback callback) { + for (int i = mCallbacks.size() - 1; i >= 0; i--) { + MessageHandler handler = mCallbacks.get(i); + if (callback == handler.mCallback) { return handler; } } return null; } - private boolean removeListenerLocked(Listener listener) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - if (listener == mListeners.get(i).mListener) { - mListeners.remove(i); + private boolean removeCallbackLocked(Callback callback) { + for (int i = mCallbacks.size() - 1; i >= 0; i--) { + if (callback == mCallbacks.get(i).mCallback) { + mCallbacks.remove(i); return true; } } @@ -204,8 +204,8 @@ public final class TransportPerformer { private void post(int what, Object obj) { synchronized (mLock) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).post(what, obj); + for (int i = mCallbacks.size() - 1; i >= 0; i--) { + mCallbacks.get(i).post(what, obj); } } } @@ -215,10 +215,10 @@ public final class TransportPerformer { } /** - * Extend Listener to handle transport controls. Listeners can be registered - * using {@link #addListener}. + * Extend to handle transport controls. Callbacks can be registered using + * {@link #addCallback}. */ - public static abstract class Listener { + public static abstract class Callback { /** * Override to handle requests to begin playback. @@ -235,13 +235,13 @@ public final class TransportPerformer { /** * Override to handle requests to skip to the next media item. */ - public void onNext() { + public void onSkipToNext() { } /** * Override to handle requests to skip to the previous media item. */ - public void onPrevious() { + public void onSkipToPrevious() { } /** @@ -275,7 +275,7 @@ public final class TransportPerformer { * * @param rating */ - public void onRate(Rating rating) { + public void onSetRating(Rating rating) { } /** @@ -284,6 +284,7 @@ public final class TransportPerformer { * {@link #setPlaybackState}. * * @param focusChange The type of focus change, TBD. + * @hide */ public void onRouteFocusChange(int focusChange) { } @@ -300,11 +301,11 @@ public final class TransportPerformer { private static final int MESSAGE_SEEK_TO = 8; private static final int MESSAGE_RATE = 9; - private Listener mListener; + private TransportPerformer.Callback mCallback; - public MessageHandler(Looper looper, Listener cb) { + public MessageHandler(Looper looper, TransportPerformer.Callback cb) { super(looper); - mListener = cb; + mCallback = cb; } public void post(int what, Object obj) { @@ -319,31 +320,31 @@ public final class TransportPerformer { public void handleMessage(Message msg) { switch (msg.what) { case MESSAGE_PLAY: - mListener.onPlay(); + mCallback.onPlay(); break; case MESSAGE_PAUSE: - mListener.onPause(); + mCallback.onPause(); break; case MESSAGE_STOP: - mListener.onStop(); + mCallback.onStop(); break; case MESSAGE_NEXT: - mListener.onNext(); + mCallback.onSkipToNext(); break; case MESSAGE_PREVIOUS: - mListener.onPrevious(); + mCallback.onSkipToPrevious(); break; case MESSAGE_FAST_FORWARD: - mListener.onFastForward(); + mCallback.onFastForward(); break; case MESSAGE_REWIND: - mListener.onRewind(); + mCallback.onRewind(); break; case MESSAGE_SEEK_TO: - mListener.onSeekTo((Long) msg.obj); + mCallback.onSeekTo((Long) msg.obj); break; case MESSAGE_RATE: - mListener.onRate((Rating) msg.obj); + mCallback.onSetRating((Rating) msg.obj); break; } } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 030e3ed..c909a54 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -66,13 +66,13 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { * These are the playback states that count as currently active. */ private static final int[] ACTIVE_STATES = { - PlaybackState.PLAYSTATE_FAST_FORWARDING, - PlaybackState.PLAYSTATE_REWINDING, - PlaybackState.PLAYSTATE_SKIPPING_BACKWARDS, - PlaybackState.PLAYSTATE_SKIPPING_FORWARDS, - PlaybackState.PLAYSTATE_BUFFERING, - PlaybackState.PLAYSTATE_CONNECTING, - PlaybackState.PLAYSTATE_PLAYING }; + PlaybackState.STATE_FAST_FORWARDING, + PlaybackState.STATE_REWINDING, + PlaybackState.STATE_SKIPPING_TO_PREVIOUS, + PlaybackState.STATE_SKIPPING_TO_NEXT, + PlaybackState.STATE_BUFFERING, + PlaybackState.STATE_CONNECTING, + PlaybackState.STATE_PLAYING }; /** * The length of time a session will still be considered active after @@ -301,7 +301,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { if (isActiveState(state)) { return true; } - if (state == mPlaybackState.PLAYSTATE_PAUSED) { + if (state == mPlaybackState.STATE_PAUSED) { long inactiveTime = SystemClock.uptimeMillis() - mLastActiveTime; if (inactiveTime < ACTIVE_BUFFER) { return true; @@ -509,12 +509,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } PlaybackState result = null; if (state != null) { - if (state.getState() == PlaybackState.PLAYSTATE_PLAYING - || state.getState() == PlaybackState.PLAYSTATE_FAST_FORWARDING - || state.getState() == PlaybackState.PLAYSTATE_REWINDING) { + if (state.getState() == PlaybackState.STATE_PLAYING + || state.getState() == PlaybackState.STATE_FAST_FORWARDING + || state.getState() == PlaybackState.STATE_REWINDING) { long updateTime = state.getLastPositionUpdateTime(); if (updateTime > 0) { - long position = (long) (state.getRate() + long position = (long) (state.getPlaybackRate() * (SystemClock.elapsedRealtime() - updateTime)) + state.getPosition(); if (duration >= 0 && position > duration) { position = duration; @@ -522,7 +522,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { position = 0; } result = new PlaybackState(state); - result.setState(state.getState(), position, state.getRate()); + result.setState(state.getState(), position, state.getPlaybackRate()); } } } @@ -588,7 +588,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { public void setPlaybackState(PlaybackState state) { int oldState = mPlaybackState == null ? 0 : mPlaybackState.getState(); int newState = state == null ? 0 : state.getState(); - if (isActiveState(oldState) && newState == PlaybackState.PLAYSTATE_PAUSED) { + if (isActiveState(oldState) && newState == PlaybackState.STATE_PAUSED) { mLastActiveTime = SystemClock.elapsedRealtime(); } mPlaybackState = state; @@ -649,14 +649,16 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { mCb = cb; } - public void sendMediaButton(KeyEvent keyEvent, int sequenceId, ResultReceiver cb) { + public boolean sendMediaButton(KeyEvent keyEvent, int sequenceId, ResultReceiver cb) { Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); mediaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent); try { mCb.onMediaButton(mediaButtonIntent, sequenceId, cb); + return true; } catch (RemoteException e) { Slog.e(TAG, "Remote failure in sendMediaRequest.", e); } + return false; } public void sendCommand(String command, Bundle extras, ResultReceiver cb) { @@ -788,8 +790,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { } @Override - public void sendMediaButton(KeyEvent mediaButtonIntent) { - mSessionCb.sendMediaButton(mediaButtonIntent, 0, null); + public boolean sendMediaButton(KeyEvent mediaButtonIntent) { + return mSessionCb.sendMediaButton(mediaButtonIntent, 0, null); } @Override diff --git a/services/core/java/com/android/server/media/MediaSessionStack.java b/services/core/java/com/android/server/media/MediaSessionStack.java index 7ba9212..56236f8 100644 --- a/services/core/java/com/android/server/media/MediaSessionStack.java +++ b/services/core/java/com/android/server/media/MediaSessionStack.java @@ -33,18 +33,18 @@ public class MediaSessionStack { * bump priority regardless of the old state. */ private static final int[] ALWAYS_PRIORITY_STATES = { - PlaybackState.PLAYSTATE_FAST_FORWARDING, - PlaybackState.PLAYSTATE_REWINDING, - PlaybackState.PLAYSTATE_SKIPPING_BACKWARDS, - PlaybackState.PLAYSTATE_SKIPPING_FORWARDS }; + PlaybackState.STATE_FAST_FORWARDING, + PlaybackState.STATE_REWINDING, + PlaybackState.STATE_SKIPPING_TO_PREVIOUS, + PlaybackState.STATE_SKIPPING_TO_NEXT }; /** * These are states that usually indicate the user took an action if they * were entered from a non-priority state. */ private static final int[] TRANSITION_PRIORITY_STATES = { - PlaybackState.PLAYSTATE_BUFFERING, - PlaybackState.PLAYSTATE_CONNECTING, - PlaybackState.PLAYSTATE_PLAYING }; + PlaybackState.STATE_BUFFERING, + PlaybackState.STATE_CONNECTING, + PlaybackState.STATE_PLAYING }; private final ArrayList mSessions = new ArrayList(); diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java index 158f5e4..ee407ad 100644 --- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java +++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java @@ -99,10 +99,10 @@ public class OnePlayerActivity extends Activity { switch (v.getId()) { case R.id.play_button: Log.d(TAG, "Play button pressed, in state " + mPlaybackState); - if (mPlaybackState == PlaybackState.PLAYSTATE_PAUSED - || mPlaybackState == PlaybackState.PLAYSTATE_STOPPED) { + if (mPlaybackState == PlaybackState.STATE_PAUSED + || mPlaybackState == PlaybackState.STATE_STOPPED) { mPlayer.play(); - } else if (mPlaybackState == PlaybackState.PLAYSTATE_PLAYING) { + } else if (mPlaybackState == PlaybackState.STATE_PLAYING) { mPlayer.pause(); } break; @@ -126,31 +126,31 @@ public class OnePlayerActivity extends Activity { boolean enableControls = true; StringBuilder statusBuilder = new StringBuilder(); switch (mPlaybackState) { - case PlaybackState.PLAYSTATE_PLAYING: + case PlaybackState.STATE_PLAYING: statusBuilder.append("playing"); mPlayButton.setText("Pause"); enablePlay = true; break; - case PlaybackState.PLAYSTATE_PAUSED: + case PlaybackState.STATE_PAUSED: statusBuilder.append("paused"); mPlayButton.setText("Play"); enablePlay = true; break; - case PlaybackState.PLAYSTATE_STOPPED: + case PlaybackState.STATE_STOPPED: statusBuilder.append("ended"); mPlayButton.setText("Play"); enablePlay = true; break; - case PlaybackState.PLAYSTATE_ERROR: + case PlaybackState.STATE_ERROR: statusBuilder.append("error: ").append(state.getErrorMessage()); break; - case PlaybackState.PLAYSTATE_BUFFERING: + case PlaybackState.STATE_BUFFERING: statusBuilder.append("buffering"); break; - case PlaybackState.PLAYSTATE_NONE: + case PlaybackState.STATE_NONE: statusBuilder.append("none"); break; - case PlaybackState.PLAYSTATE_CONNECTING: + case PlaybackState.STATE_CONNECTING: statusBuilder.append("connecting"); enableControls = false; break; diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerService.java b/tests/OneMedia/src/com/android/onemedia/PlayerService.java index 0ad6dd1..934f4ef 100644 --- a/tests/OneMedia/src/com/android/onemedia/PlayerService.java +++ b/tests/OneMedia/src/com/android/onemedia/PlayerService.java @@ -103,11 +103,11 @@ public class PlayerService extends Service { @Override public void onPlayStateChanged(PlaybackState state) { switch (state.getState()) { - case PlaybackState.PLAYSTATE_PLAYING: + case PlaybackState.STATE_PLAYING: onPlaybackStarted(); break; - case PlaybackState.PLAYSTATE_STOPPED: - case PlaybackState.PLAYSTATE_ERROR: + case PlaybackState.STATE_STOPPED: + case PlaybackState.STATE_ERROR: onPlaybackEnded(); break; } diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java index 94d0851..97a0a08 100644 --- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java +++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java @@ -85,7 +85,7 @@ public class PlayerSession { mSession = man.createSession("OneMedia"); mSession.addCallback(mCallback); mPerformer = mSession.getTransportPerformer(); - mPerformer.addListener(new TransportListener()); + mPerformer.addCallback(new TransportListener()); mPerformer.setPlaybackState(mPlaybackState); mSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); mSession.setRouteOptions(mRouteOptions); @@ -120,7 +120,7 @@ public class PlayerSession { } private void updateState(int newState) { - float rate = newState == PlaybackState.PLAYSTATE_PLAYING ? 1 : 0; + float rate = newState == PlaybackState.STATE_PLAYING ? 1 : 0; long position = mRenderer == null ? -1 : mRenderer.getSeekPosition(); mPlaybackState.setState(newState, position, rate); mPerformer.setPlaybackState(mPlaybackState); @@ -135,7 +135,7 @@ public class PlayerSession { @Override public void onError(int type, int extra, Bundle extras, Throwable error) { Log.d(TAG, "Sending onError with type " + type + " and extra " + extra); - mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, -1, 0); + mPlaybackState.setState(PlaybackState.STATE_ERROR, -1, 0); if (error != null) { mPlaybackState.setErrorMessage(error.getLocalizedMessage()); } @@ -157,23 +157,23 @@ public class PlayerSession { switch (newState) { case Renderer.STATE_ENDED: case Renderer.STATE_STOPPED: - mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED, position, 0); + mPlaybackState.setState(PlaybackState.STATE_STOPPED, position, 0); break; case Renderer.STATE_INIT: case Renderer.STATE_PREPARING: - mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING, position, 0); + mPlaybackState.setState(PlaybackState.STATE_BUFFERING, position, 0); break; case Renderer.STATE_ERROR: - mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0); + mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0); break; case Renderer.STATE_PAUSED: - mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0); + mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0); break; case Renderer.STATE_PLAYING: - mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING, position, 1); + mPlaybackState.setState(PlaybackState.STATE_PLAYING, position, 1); break; default: - mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0); + mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0); mPlaybackState.setErrorMessage("unkown state"); break; } @@ -191,7 +191,7 @@ public class PlayerSession { public void onFocusLost() { Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED); long position = mRenderer == null ? -1 : mRenderer.getSeekPosition(); - mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0); + mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0); mPerformer.setPlaybackState(mPlaybackState); if (mListener != null) { mListener.onPlayStateChanged(mPlaybackState); @@ -206,7 +206,7 @@ public class PlayerSession { private class SessionCb extends MediaSession.Callback { @Override - public void onMediaButton(Intent mediaRequestIntent) { + public void onMediaButtonEvent(Intent mediaRequestIntent) { if (Intent.ACTION_MEDIA_BUTTON.equals(mediaRequestIntent.getAction())) { KeyEvent event = (KeyEvent) mediaRequestIntent .getParcelableExtra(Intent.EXTRA_KEY_EVENT); @@ -233,12 +233,12 @@ public class PlayerSession { mRoute = null; mRenderer = new LocalRenderer(mContext, null); mRenderer.registerListener(mRenderListener); - updateState(PlaybackState.PLAYSTATE_NONE); + updateState(PlaybackState.STATE_NONE); } else { // Use remote route mSession.connect(route, mRouteOptions.get(0)); mRenderer = null; - updateState(PlaybackState.PLAYSTATE_CONNECTING); + updateState(PlaybackState.STATE_CONNECTING); } } @@ -249,7 +249,7 @@ public class PlayerSession { mRouteControls.addListener(mRouteListener); Log.d(TAG, "Connected to route, registering listener"); mRenderer = new OneMRPRenderer(mRouteControls); - updateState(PlaybackState.PLAYSTATE_NONE); + updateState(PlaybackState.STATE_NONE); } @Override @@ -258,7 +258,7 @@ public class PlayerSession { } } - private class TransportListener extends TransportPerformer.Listener { + private class TransportListener extends TransportPerformer.Callback { @Override public void onPlay() { mRenderer.onPlay(); diff --git a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java index 6537d49..f2d691c 100644 --- a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java +++ b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java @@ -149,7 +149,7 @@ public class OneMediaRouteProvider extends RouteProviderService { public void onError(int type, int extra, Bundle extras, Throwable error) { Log.d(TAG, "Sending onError with type " + type + " and extra " + extra); if (mControls != null) { - mControls.sendPlaybackChangeEvent(PlaybackState.PLAYSTATE_ERROR); + mControls.sendPlaybackChangeEvent(PlaybackState.STATE_ERROR); } } @@ -165,23 +165,23 @@ public class OneMediaRouteProvider extends RouteProviderService { switch (newState) { case Renderer.STATE_ENDED: case Renderer.STATE_STOPPED: - mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED, position, 0); + mPlaybackState.setState(PlaybackState.STATE_STOPPED, position, 0); break; case Renderer.STATE_INIT: case Renderer.STATE_PREPARING: - mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING, position, 0); + mPlaybackState.setState(PlaybackState.STATE_BUFFERING, position, 0); break; case Renderer.STATE_ERROR: - mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0); + mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0); break; case Renderer.STATE_PAUSED: - mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0); + mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0); break; case Renderer.STATE_PLAYING: - mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING, position, 1); + mPlaybackState.setState(PlaybackState.STATE_PLAYING, position, 1); break; default: - mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0); + mPlaybackState.setState(PlaybackState.STATE_ERROR, position, 0); mPlaybackState.setErrorMessage("unkown state"); break; } @@ -196,7 +196,7 @@ public class OneMediaRouteProvider extends RouteProviderService { @Override public void onFocusLost() { Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED); - mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, mRenderer.getSeekPosition(), 0); + mPlaybackState.setState(PlaybackState.STATE_PAUSED, mRenderer.getSeekPosition(), 0); mRenderer.onPause(); } -- cgit v1.1 From c47fa84b0a6bda48c38ba8822481ce613bafd019 Mon Sep 17 00:00:00 2001 From: RoboErik Date: Wed, 28 May 2014 17:36:42 -0700 Subject: Refactor transport controls APIs This merges TransportPerformer into MediaSession + a TransportControlsCallback and makes TransportController into an inner class on MediaController called TransportControls. Also makes the PlaybackState and Metadata part of the session APIs instead of transport controls. Change-Id: I16ad392e6d318abe3119ad5d89656d253af25e16 --- api/current.txt | 91 ++--- media/java/android/media/RemoteControlClient.java | 10 +- .../android/media/session/MediaController.java | 241 ++++++++++-- media/java/android/media/session/MediaSession.java | 406 +++++++++++++++++---- .../media/session/MediaSessionLegacyHelper.java | 18 +- .../media/session/RemoteVolumeProvider.java | 33 +- .../android/media/session/TransportController.java | 343 ----------------- .../android/media/session/TransportPerformer.java | 352 ------------------ .../src/com/android/onemedia/PlayerController.java | 13 +- .../src/com/android/onemedia/PlayerSession.java | 17 +- 10 files changed, 627 insertions(+), 897 deletions(-) delete mode 100644 media/java/android/media/session/TransportController.java delete mode 100644 media/java/android/media/session/TransportPerformer.java diff --git a/api/current.txt b/api/current.txt index acf6e87..34a3a48 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15723,28 +15723,49 @@ package android.media.session { method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler); method public boolean dispatchMediaButtonEvent(android.view.KeyEvent); method public static android.media.session.MediaController fromToken(android.media.session.MediaSessionToken); - method public android.media.session.TransportController getTransportController(); + method public android.media.MediaMetadata getMetadata(); + method public android.media.session.PlaybackState getPlaybackState(); + method public int getRatingType(); + method public android.media.session.MediaController.TransportControls getTransportControls(); method public void removeCallback(android.media.session.MediaController.Callback); method public void sendControlCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver); } public static abstract class MediaController.Callback { ctor public MediaController.Callback(); + method public void onMetadataChanged(android.media.MediaMetadata); + method public void onPlaybackStateChanged(android.media.session.PlaybackState); method public void onSessionEvent(java.lang.String, android.os.Bundle); } + public final class MediaController.TransportControls { + method public void fastForward(); + method public void pause(); + method public void play(); + method public void rewind(); + method public void seekTo(long); + method public void setRating(android.media.Rating); + method public void skipToNext(); + method public void skipToPrevious(); + method public void stop(); + } + public final class MediaSession { method public void addCallback(android.media.session.MediaSession.Callback); method public void addCallback(android.media.session.MediaSession.Callback, android.os.Handler); + method public void addTransportControlsCallback(android.media.session.MediaSession.TransportControlsCallback); + method public void addTransportControlsCallback(android.media.session.MediaSession.TransportControlsCallback, android.os.Handler); method public android.media.session.MediaSessionToken getSessionToken(); - method public android.media.session.TransportPerformer getTransportPerformer(); method public boolean isActive(); method public void release(); method public void removeCallback(android.media.session.MediaSession.Callback); + method public void removeTransportControlsCallback(android.media.session.MediaSession.TransportControlsCallback); method public void sendSessionEvent(java.lang.String, android.os.Bundle); method public void setActive(boolean); method public void setFlags(int); method public void setLaunchPendingIntent(android.app.PendingIntent); + method public void setMetadata(android.media.MediaMetadata); + method public void setPlaybackState(android.media.session.PlaybackState); method public void setPlaybackToLocal(int); method public void setPlaybackToRemote(android.media.session.RemoteVolumeProvider); field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1 @@ -15757,6 +15778,19 @@ package android.media.session { method public void onMediaButtonEvent(android.content.Intent); } + public static abstract class MediaSession.TransportControlsCallback { + ctor public MediaSession.TransportControlsCallback(); + method public void onFastForward(); + method public void onPause(); + method public void onPlay(); + method public void onRewind(); + method public void onSeekTo(long); + method public void onSetRating(android.media.Rating); + method public void onSkipToNext(); + method public void onSkipToPrevious(); + method public void onStop(); + } + public final class MediaSessionManager { method public android.media.session.MediaSession createSession(java.lang.String); } @@ -15808,60 +15842,15 @@ package android.media.session { public abstract class RemoteVolumeProvider { ctor public RemoteVolumeProvider(int, int); - method public final int getFlags(); method public final int getMaxVolume(); + method public final int getVolumeControl(); method public final void notifyVolumeChanged(); method public void onAdjustVolumeBy(int); method public abstract int onGetCurrentVolume(); method public void onSetVolumeTo(int); - field public static final int VOLUME_CONTROL_ABSOLUTE = 4; // 0x4 - field public static final int VOLUME_CONTROL_FIXED = 1; // 0x1 - field public static final int VOLUME_CONTROL_RELATIVE = 2; // 0x2 - } - - public final class TransportController { - method public void addStateListener(android.media.session.TransportController.TransportStateListener); - method public void addStateListener(android.media.session.TransportController.TransportStateListener, android.os.Handler); - method public void fastForward(); - method public android.media.MediaMetadata getMetadata(); - method public android.media.session.PlaybackState getPlaybackState(); - method public int getRatingType(); - method public void pause(); - method public void play(); - method public void removeStateListener(android.media.session.TransportController.TransportStateListener); - method public void rewind(); - method public void seekTo(long); - method public void setRating(android.media.Rating); - method public void skipToNext(); - method public void skipToPrevious(); - method public void stop(); - } - - public static abstract class TransportController.TransportStateListener { - ctor public TransportController.TransportStateListener(); - method public void onMetadataChanged(android.media.MediaMetadata); - method public void onPlaybackStateChanged(android.media.session.PlaybackState); - } - - public final class TransportPerformer { - method public void addCallback(android.media.session.TransportPerformer.Callback); - method public void addCallback(android.media.session.TransportPerformer.Callback, android.os.Handler); - method public void removeCallback(android.media.session.TransportPerformer.Callback); - method public void setMetadata(android.media.MediaMetadata); - method public void setPlaybackState(android.media.session.PlaybackState); - } - - public static abstract class TransportPerformer.Callback { - ctor public TransportPerformer.Callback(); - method public void onFastForward(); - method public void onPause(); - method public void onPlay(); - method public void onRewind(); - method public void onSeekTo(long); - method public void onSetRating(android.media.Rating); - method public void onSkipToNext(); - method public void onSkipToPrevious(); - method public void onStop(); + field public static final int VOLUME_CONTROL_ABSOLUTE = 2; // 0x2 + field public static final int VOLUME_CONTROL_FIXED = 0; // 0x0 + field public static final int VOLUME_CONTROL_RELATIVE = 1; // 0x1 } } diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java index b89affd..0caea5f 100644 --- a/media/java/android/media/RemoteControlClient.java +++ b/media/java/android/media/RemoteControlClient.java @@ -27,7 +27,6 @@ import android.graphics.RectF; import android.media.session.MediaSessionLegacyHelper; import android.media.session.PlaybackState; import android.media.session.MediaSession; -import android.media.session.TransportPerformer; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -584,7 +583,7 @@ public class RemoteControlClient // USE_SESSIONS if (mSession != null && mMetadataBuilder != null) { - mSession.getTransportPerformer().setMetadata(mMetadataBuilder.build()); + mSession.setMetadata(mMetadataBuilder.build()); } mApplied = true; } @@ -702,7 +701,7 @@ public class RemoteControlClient mSessionPlaybackState.setState(pbState, hasPosition ? mPlaybackPositionMs : PlaybackState.PLAYBACK_POSITION_UNKNOWN, playbackSpeed); - mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState); + mSession.setPlaybackState(mSessionPlaybackState); } } } @@ -789,7 +788,7 @@ public class RemoteControlClient if (mSession != null) { mSessionPlaybackState.setActions(PlaybackState .getActionsFromRccControlFlags(transportControlFlags)); - mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState); + mSession.setPlaybackState(mSessionPlaybackState); } } } @@ -1317,7 +1316,8 @@ public class RemoteControlClient } // USE_SESSIONS - private TransportPerformer.Callback mTransportListener = new TransportPerformer.Callback() { + private MediaSession.TransportControlsCallback mTransportListener + = new MediaSession.TransportControlsCallback() { @Override public void onSeekTo(long pos) { diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java index 63c0839..caff1ad 100644 --- a/media/java/android/media/session/MediaController.java +++ b/media/java/android/media/session/MediaController.java @@ -17,6 +17,7 @@ package android.media.session; import android.media.MediaMetadata; +import android.media.Rating; import android.os.Bundle; import android.os.Handler; import android.os.Looper; @@ -45,8 +46,8 @@ public final class MediaController { private static final String TAG = "SessionController"; private static final int MSG_EVENT = 1; - private static final int MESSAGE_PLAYBACK_STATE = 2; - private static final int MESSAGE_METADATA = 3; + private static final int MSG_UPDATE_PLAYBACK_STATE = 2; + private static final int MSG_UPDATE_METADATA = 3; private static final int MSG_ROUTE = 4; private final ISessionController mSessionBinder; @@ -57,10 +58,11 @@ public final class MediaController { private boolean mCbRegistered = false; - private TransportController mTransportController; + private TransportControls mTransportController; private MediaController(ISessionController sessionBinder) { mSessionBinder = sessionBinder; + mTransportController = new TransportControls(); } /** @@ -70,9 +72,6 @@ public final class MediaController { MediaController controller = new MediaController(sessionBinder); try { controller.mSessionBinder.registerCallbackListener(controller.mCbStub); - if (controller.mSessionBinder.isTransportControlEnabled()) { - controller.mTransportController = new TransportController(sessionBinder); - } } catch (RemoteException e) { Log.wtf(TAG, "MediaController created with expired token", e); controller = null; @@ -93,12 +92,11 @@ public final class MediaController { } /** - * Get a TransportController if the session supports it. If it is not - * supported null will be returned. + * Get a {@link TransportControls} instance for this session. * - * @return A TransportController or null + * @return A controls instance */ - public TransportController getTransportController() { + public TransportControls getTransportControls() { return mTransportController; } @@ -119,12 +117,63 @@ public final class MediaController { try { return mSessionBinder.sendMediaButton(keyEvent); } catch (RemoteException e) { - Log.d(TAG, "Dead object in sendMediaButton", e); + // System is dead. =( } return false; } /** + * Get the current playback state for this session. + * + * @return The current PlaybackState or null + */ + public PlaybackState getPlaybackState() { + try { + return mSessionBinder.getPlaybackState(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling getPlaybackState.", e); + return null; + } + } + + /** + * Get the current metadata for this session. + * + * @return The current MediaMetadata or null. + */ + public MediaMetadata getMetadata() { + try { + return mSessionBinder.getMetadata(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling getMetadata.", e); + return null; + } + } + + /** + * Get the rating type supported by the session. One of: + *
      + *
    • {@link Rating#RATING_NONE}
    • + *
    • {@link Rating#RATING_HEART}
    • + *
    • {@link Rating#RATING_THUMB_UP_DOWN}
    • + *
    • {@link Rating#RATING_3_STARS}
    • + *
    • {@link Rating#RATING_4_STARS}
    • + *
    • {@link Rating#RATING_5_STARS}
    • + *
    • {@link Rating#RATING_PERCENTAGE}
    • + *
    + * + * @return The supported rating type + */ + public int getRatingType() { + try { + return mSessionBinder.getRatingType(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling getRatingType.", e); + return Rating.RATING_NONE; + } + } + + /** * Adds a callback to receive updates from the Session. Updates will be * posted on the caller's thread. * @@ -255,18 +304,10 @@ public final class MediaController { return null; } - private void postEvent(String event, Bundle extras) { + private final void postMessage(int what, Object obj, Bundle data) { synchronized (mLock) { for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(MSG_EVENT, event, extras); - } - } - } - - private void postRouteChanged(RouteInfo route) { - synchronized (mLock) { - for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(MSG_ROUTE, route, null); + mCallbacks.get(i).post(what, obj, data); } } } @@ -294,6 +335,143 @@ public final class MediaController { */ public void onRouteChanged(RouteInfo route) { } + + /** + * Override to handle changes in playback state. + * + * @param state The new playback state of the session + */ + public void onPlaybackStateChanged(PlaybackState state) { + } + + /** + * Override to handle changes to the current metadata. + * + * @see MediaMetadata + * @param metadata The current metadata for the session or null + */ + public void onMetadataChanged(MediaMetadata metadata) { + } + } + + /** + * Interface for controlling media playback on a session. This allows an app + * to send media transport commands to the session. + */ + public final class TransportControls { + private static final String TAG = "TransportController"; + + private TransportControls() { + } + + /** + * Request that the player start its playback at its current position. + */ + public void play() { + try { + mSessionBinder.play(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling play.", e); + } + } + + /** + * Request that the player pause its playback and stay at its current + * position. + */ + public void pause() { + try { + mSessionBinder.pause(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling pause.", e); + } + } + + /** + * Request that the player stop its playback; it may clear its state in + * whatever way is appropriate. + */ + public void stop() { + try { + mSessionBinder.stop(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling stop.", e); + } + } + + /** + * Move to a new location in the media stream. + * + * @param pos Position to move to, in milliseconds. + */ + public void seekTo(long pos) { + try { + mSessionBinder.seekTo(pos); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling seekTo.", e); + } + } + + /** + * Start fast forwarding. If playback is already fast forwarding this + * may increase the rate. + */ + public void fastForward() { + try { + mSessionBinder.fastForward(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling fastForward.", e); + } + } + + /** + * Skip to the next item. + */ + public void skipToNext() { + try { + mSessionBinder.next(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling next.", e); + } + } + + /** + * Start rewinding. If playback is already rewinding this may increase + * the rate. + */ + public void rewind() { + try { + mSessionBinder.rewind(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling rewind.", e); + } + } + + /** + * Skip to the previous item. + */ + public void skipToPrevious() { + try { + mSessionBinder.previous(); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling previous.", e); + } + } + + /** + * Rate the current content. This will cause the rating to be set for + * the current user. The Rating type must match the type returned by + * {@link #getRatingType()}. + * + * @param rating The rating to set for the current content + */ + public void setRating(Rating rating) { + try { + mSessionBinder.rate(rating); + } catch (RemoteException e) { + Log.wtf(TAG, "Error calling rate.", e); + } + } } private final static class CallbackStub extends ISessionControllerCallback.Stub { @@ -307,7 +485,7 @@ public final class MediaController { public void onEvent(String event, Bundle extras) { MediaController controller = mController.get(); if (controller != null) { - controller.postEvent(event, extras); + controller.postMessage(MSG_EVENT, event, extras); } } @@ -315,7 +493,7 @@ public final class MediaController { public void onRouteChanged(RouteInfo route) { MediaController controller = mController.get(); if (controller != null) { - controller.postRouteChanged(route); + controller.postMessage(MSG_ROUTE, route, null); } } @@ -323,10 +501,7 @@ public final class MediaController { public void onPlaybackStateChanged(PlaybackState state) { MediaController controller = mController.get(); if (controller != null) { - TransportController tc = controller.getTransportController(); - if (tc != null) { - tc.postPlaybackStateChanged(state); - } + controller.postMessage(MSG_UPDATE_PLAYBACK_STATE, state, null); } } @@ -334,10 +509,7 @@ public final class MediaController { public void onMetadataChanged(MediaMetadata metadata) { MediaController controller = mController.get(); if (controller != null) { - TransportController tc = controller.getTransportController(); - if (tc != null) { - tc.postMetadataChanged(metadata); - } + controller.postMessage(MSG_UPDATE_METADATA, metadata, null); } } @@ -359,6 +531,13 @@ public final class MediaController { break; case MSG_ROUTE: mCallback.onRouteChanged((RouteInfo) msg.obj); + break; + case MSG_UPDATE_PLAYBACK_STATE: + mCallback.onPlaybackStateChanged((PlaybackState) msg.obj); + break; + case MSG_UPDATE_METADATA: + mCallback.onMetadataChanged((MediaMetadata) msg.obj); + break; } } diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java index 51dcee1..90ccf68 100644 --- a/media/java/android/media/session/MediaSession.java +++ b/media/java/android/media/session/MediaSession.java @@ -16,10 +16,12 @@ package android.media.session; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.PendingIntent; import android.content.Intent; -import android.media.AudioAttributes; import android.media.AudioManager; +import android.media.MediaMetadata; import android.media.Rating; import android.media.session.ISessionController; import android.media.session.ISession; @@ -52,8 +54,10 @@ import java.util.List; * the owner of the session may use {@link #getSessionToken()} to allow apps to * create a {@link MediaController} to interact with this session. *

    - * To receive commands, media keys, and other events a Callback must be set with - * {@link #addCallback(Callback)}. + * To receive commands, media keys, and other events a {@link Callback} must be + * set with {@link #addCallback(Callback)}. To receive transport control + * commands a {@link TransportControlsCallback} must be set with + * {@link #addTransportControlsCallback}. *

    * When an app is finished performing playback it must call {@link #release()} * to clean up the session and notify any controllers. @@ -70,9 +74,10 @@ public final class MediaSession { public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1 << 0; /** - * Set this flag on the session to indicate that it handles commands through - * the {@link TransportPerformer}. The performer can be retrieved by calling - * {@link #getTransportPerformer()}. + * Set this flag on the session to indicate that it handles transport + * control commands through a {@link TransportControlsCallback}. The + * callback can be retrieved by calling + * {@link #addTransportControlsCallback}. */ public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1; @@ -119,12 +124,6 @@ public final class MediaSession { */ public static final int DISCONNECT_REASON_SESSION_DESTROYED = 5; - private static final int MSG_MEDIA_BUTTON = 1; - private static final int MSG_COMMAND = 2; - private static final int MSG_ROUTE_CHANGE = 3; - private static final int MSG_ROUTE_CONNECTED = 4; - private static final int MSG_ROUTE_DISCONNECTED = 5; - private static final String KEY_COMMAND = "command"; private static final String KEY_EXTRAS = "extras"; private static final String KEY_CALLBACK = "callback"; @@ -135,12 +134,14 @@ public final class MediaSession { private final ISession mBinder; private final CallbackStub mCbStub; - private final ArrayList mCallbacks = new ArrayList(); + private final ArrayList mCallbacks + = new ArrayList(); + private final ArrayList mTransportCallbacks + = new ArrayList(); // TODO route interfaces private final ArrayMap mInterfaceListeners = new ArrayMap(); - private TransportPerformer mPerformer; private Route mRoute; private boolean mActive = false;; @@ -158,7 +159,6 @@ public final class MediaSession { throw new RuntimeException("Dead object in MediaSessionController constructor: ", e); } mSessionToken = new MediaSessionToken(controllerBinder); - mPerformer = new TransportPerformer(mBinder); } /** @@ -191,7 +191,8 @@ public final class MediaSession { if (handler == null) { handler = new Handler(); } - MessageHandler msgHandler = new MessageHandler(handler.getLooper(), callback); + CallbackMessageHandler msgHandler = new CallbackMessageHandler(handler.getLooper(), + callback); mCallbacks.add(msgHandler); } } @@ -208,18 +209,6 @@ public final class MediaSession { } /** - * Retrieves the {@link TransportPerformer} for this session. To receive - * commands through the performer you must also set the - * {@link #FLAG_HANDLES_TRANSPORT_CONTROLS} flag using - * {@link #setFlags(int)}. - * - * @return The performer associated with this session. - */ - public TransportPerformer getTransportPerformer() { - return mPerformer; - } - - /** * Set an intent for launching UI for this Session. This can be used as a * quick link to an ongoing media screen. * @@ -430,12 +419,160 @@ public final class MediaSession { return true; } - private MessageHandler getHandlerForCallbackLocked(Callback cb) { + /** + * Add a callback to receive transport controls on, such as play, rewind, or + * fast forward. + * + * @param callback The callback object + */ + public void addTransportControlsCallback(@NonNull TransportControlsCallback callback) { + addTransportControlsCallback(callback, null); + } + + /** + * Add a callback to receive transport controls on, such as play, rewind, or + * fast forward. The updates will be posted to the specified handler. If no + * handler is provided they will be posted to the caller's thread. + * + * @param callback The callback to receive updates on + * @param handler The handler to post the updates on + */ + public void addTransportControlsCallback(@NonNull TransportControlsCallback callback, + @Nullable Handler handler) { + if (callback == null) { + throw new IllegalArgumentException("Callback cannot be null"); + } + synchronized (mLock) { + if (getTransportControlsHandlerForCallbackLocked(callback) != null) { + Log.w(TAG, "Callback is already added, ignoring"); + return; + } + if (handler == null) { + handler = new Handler(); + } + TransportMessageHandler msgHandler = new TransportMessageHandler(handler.getLooper(), + callback); + mTransportCallbacks.add(msgHandler); + } + } + + /** + * Stop receiving transport controls on the specified callback. If an update + * has already been posted you may still receive it after this call returns. + * + * @param callback The callback to stop receiving updates on + */ + public void removeTransportControlsCallback(@NonNull TransportControlsCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("Callback cannot be null"); + } + synchronized (mLock) { + removeTransportControlsCallbackLocked(callback); + } + } + + /** + * Update the current playback state. + * + * @param state The current state of playback + */ + public void setPlaybackState(PlaybackState state) { + try { + mBinder.setPlaybackState(state); + } catch (RemoteException e) { + Log.wtf(TAG, "Dead object in setPlaybackState.", e); + } + } + + /** + * Update the current metadata. New metadata can be created using + * {@link android.media.MediaMetadata.Builder}. + * + * @param metadata The new metadata + */ + public void setMetadata(MediaMetadata metadata) { + try { + mBinder.setMetadata(metadata); + } catch (RemoteException e) { + Log.wtf(TAG, "Dead object in setPlaybackState.", e); + } + } + + private void dispatchPlay() { + postToTransportCallbacks(TransportMessageHandler.MSG_PLAY); + } + + private void dispatchPause() { + postToTransportCallbacks(TransportMessageHandler.MSG_PAUSE); + } + + private void dispatchStop() { + postToTransportCallbacks(TransportMessageHandler.MSG_STOP); + } + + private void dispatchNext() { + postToTransportCallbacks(TransportMessageHandler.MSG_NEXT); + } + + private void dispatchPrevious() { + postToTransportCallbacks(TransportMessageHandler.MSG_PREVIOUS); + } + + private void dispatchFastForward() { + postToTransportCallbacks(TransportMessageHandler.MSG_FAST_FORWARD); + } + + private void dispatchRewind() { + postToTransportCallbacks(TransportMessageHandler.MSG_REWIND); + } + + private void dispatchSeekTo(long pos) { + postToTransportCallbacks(TransportMessageHandler.MSG_SEEK_TO, pos); + } + + private void dispatchRate(Rating rating) { + postToTransportCallbacks(TransportMessageHandler.MSG_RATE, rating); + } + + private TransportMessageHandler getTransportControlsHandlerForCallbackLocked( + TransportControlsCallback callback) { + for (int i = mTransportCallbacks.size() - 1; i >= 0; i--) { + TransportMessageHandler handler = mTransportCallbacks.get(i); + if (callback == handler.mCallback) { + return handler; + } + } + return null; + } + + private boolean removeTransportControlsCallbackLocked(TransportControlsCallback callback) { + for (int i = mTransportCallbacks.size() - 1; i >= 0; i--) { + if (callback == mTransportCallbacks.get(i).mCallback) { + mTransportCallbacks.remove(i); + return true; + } + } + return false; + } + + private void postToTransportCallbacks(int what, Object obj) { + synchronized (mLock) { + for (int i = mTransportCallbacks.size() - 1; i >= 0; i--) { + mTransportCallbacks.get(i).post(what, obj); + } + } + } + + private void postToTransportCallbacks(int what) { + postToTransportCallbacks(what, null); + } + + private CallbackMessageHandler getHandlerForCallbackLocked(Callback cb) { if (cb == null) { throw new IllegalArgumentException("Callback cannot be null"); } for (int i = mCallbacks.size() - 1; i >= 0; i--) { - MessageHandler handler = mCallbacks.get(i); + CallbackMessageHandler handler = mCallbacks.get(i); if (cb == handler.mCallback) { return handler; } @@ -448,7 +585,7 @@ public final class MediaSession { throw new IllegalArgumentException("Callback cannot be null"); } for (int i = mCallbacks.size() - 1; i >= 0; i--) { - MessageHandler handler = mCallbacks.get(i); + CallbackMessageHandler handler = mCallbacks.get(i); if (cb == handler.mCallback) { mCallbacks.remove(i); return true; @@ -461,7 +598,7 @@ public final class MediaSession { Command cmd = new Command(command, extras, resultCb); synchronized (mLock) { for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(MSG_COMMAND, cmd); + mCallbacks.get(i).post(CallbackMessageHandler.MSG_COMMAND, cmd); } } } @@ -469,7 +606,7 @@ public final class MediaSession { private void postMediaButton(Intent mediaButtonIntent) { synchronized (mLock) { for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(MSG_MEDIA_BUTTON, mediaButtonIntent); + mCallbacks.get(i).post(CallbackMessageHandler.MSG_MEDIA_BUTTON, mediaButtonIntent); } } } @@ -477,7 +614,7 @@ public final class MediaSession { private void postRequestRouteChange(RouteInfo route) { synchronized (mLock) { for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(MSG_ROUTE_CHANGE, route); + mCallbacks.get(i).post(CallbackMessageHandler.MSG_ROUTE_CHANGE, route); } } } @@ -486,7 +623,7 @@ public final class MediaSession { synchronized (mLock) { mRoute = new Route(route, options, this); for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(MSG_ROUTE_CONNECTED, mRoute); + mCallbacks.get(i).post(CallbackMessageHandler.MSG_ROUTE_CONNECTED, mRoute); } } } @@ -495,16 +632,16 @@ public final class MediaSession { synchronized (mLock) { if (mRoute != null && TextUtils.equals(mRoute.getRouteInfo().getId(), route.getId())) { for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(MSG_ROUTE_DISCONNECTED, mRoute, reason); + mCallbacks.get(i).post(CallbackMessageHandler.MSG_ROUTE_DISCONNECTED, mRoute, + reason); } } } } /** - * Receives commands or updates from controllers and routes. An app can - * specify what commands and buttons it supports by setting them on the - * MediaSession. + * Receives generic commands or updates from controllers and the system. + * Callbacks may be registered using {@link #addCallback}. */ public abstract static class Callback { @@ -580,6 +717,82 @@ public final class MediaSession { } /** + * Receives transport control commands. Callbacks may be registered using + * {@link #addTransportControlsCallback}. + */ + public static abstract class TransportControlsCallback { + + /** + * Override to handle requests to begin playback. + */ + public void onPlay() { + } + + /** + * Override to handle requests to pause playback. + */ + public void onPause() { + } + + /** + * Override to handle requests to skip to the next media item. + */ + public void onSkipToNext() { + } + + /** + * Override to handle requests to skip to the previous media item. + */ + public void onSkipToPrevious() { + } + + /** + * Override to handle requests to fast forward. + */ + public void onFastForward() { + } + + /** + * Override to handle requests to rewind. + */ + public void onRewind() { + } + + /** + * Override to handle requests to stop playback. + */ + public void onStop() { + } + + /** + * Override to handle requests to seek to a specific position in ms. + * + * @param pos New position to move to, in milliseconds. + */ + public void onSeekTo(long pos) { + } + + /** + * Override to handle the item being rated. + * + * @param rating + */ + public void onSetRating(Rating rating) { + } + + /** + * Report that audio focus has changed on the app. This only happens if + * you have indicated you have started playing with + * {@link #setPlaybackState}. + * + * @param focusChange The type of focus change, TBD. + * @hide + */ + public void onRouteFocusChange(int focusChange) { + } + } + + /** * @hide */ public static class CallbackStub extends ISessionCallback.Stub { @@ -641,10 +854,7 @@ public final class MediaSession { public void onPlay() throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchPlay(); - } + session.dispatchPlay(); } } @@ -652,10 +862,7 @@ public final class MediaSession { public void onPause() throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchPause(); - } + session.dispatchPause(); } } @@ -663,10 +870,7 @@ public final class MediaSession { public void onStop() throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchStop(); - } + session.dispatchStop(); } } @@ -674,10 +878,7 @@ public final class MediaSession { public void onNext() throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchNext(); - } + session.dispatchNext(); } } @@ -685,10 +886,7 @@ public final class MediaSession { public void onPrevious() throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchPrevious(); - } + session.dispatchPrevious(); } } @@ -696,10 +894,7 @@ public final class MediaSession { public void onFastForward() throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchFastForward(); - } + session.dispatchFastForward(); } } @@ -707,10 +902,7 @@ public final class MediaSession { public void onRewind() throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchRewind(); - } + session.dispatchRewind(); } } @@ -718,10 +910,7 @@ public final class MediaSession { public void onSeekTo(long pos) throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchSeekTo(pos); - } + session.dispatchSeekTo(pos); } } @@ -729,10 +918,7 @@ public final class MediaSession { public void onRate(Rating rating) throws RemoteException { MediaSession session = mMediaSession.get(); if (session != null) { - TransportPerformer tp = session.getTransportPerformer(); - if (tp != null) { - tp.dispatchRate(rating); - } + session.dispatchRate(rating); } } @@ -758,10 +944,16 @@ public final class MediaSession { } - private class MessageHandler extends Handler { + private class CallbackMessageHandler extends Handler { + private static final int MSG_MEDIA_BUTTON = 1; + private static final int MSG_COMMAND = 2; + private static final int MSG_ROUTE_CHANGE = 3; + private static final int MSG_ROUTE_CONNECTED = 4; + private static final int MSG_ROUTE_DISCONNECTED = 5; + private MediaSession.Callback mCallback; - public MessageHandler(Looper looper, MediaSession.Callback callback) { + public CallbackMessageHandler(Looper looper, MediaSession.Callback callback) { super(looper, null, true); mCallback = callback; } @@ -813,4 +1005,64 @@ public final class MediaSession { this.stub = stub; } } + + private class TransportMessageHandler extends Handler { + private static final int MSG_PLAY = 1; + private static final int MSG_PAUSE = 2; + private static final int MSG_STOP = 3; + private static final int MSG_NEXT = 4; + private static final int MSG_PREVIOUS = 5; + private static final int MSG_FAST_FORWARD = 6; + private static final int MSG_REWIND = 7; + private static final int MSG_SEEK_TO = 8; + private static final int MSG_RATE = 9; + + private TransportControlsCallback mCallback; + + public TransportMessageHandler(Looper looper, TransportControlsCallback cb) { + super(looper); + mCallback = cb; + } + + public void post(int what, Object obj) { + obtainMessage(what, obj).sendToTarget(); + } + + public void post(int what) { + post(what, null); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_PLAY: + mCallback.onPlay(); + break; + case MSG_PAUSE: + mCallback.onPause(); + break; + case MSG_STOP: + mCallback.onStop(); + break; + case MSG_NEXT: + mCallback.onSkipToNext(); + break; + case MSG_PREVIOUS: + mCallback.onSkipToPrevious(); + break; + case MSG_FAST_FORWARD: + mCallback.onFastForward(); + break; + case MSG_REWIND: + mCallback.onRewind(); + break; + case MSG_SEEK_TO: + mCallback.onSeekTo((Long) msg.obj); + break; + case MSG_RATE: + mCallback.onSetRating((Rating) msg.obj); + break; + } + } + } } diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java index bdf3628..c303e77 100644 --- a/media/java/android/media/session/MediaSessionLegacyHelper.java +++ b/media/java/android/media/session/MediaSessionLegacyHelper.java @@ -76,13 +76,13 @@ public class MediaSessionLegacyHelper { } } - public void addRccListener(PendingIntent pi, TransportPerformer.Callback listener) { + public void addRccListener(PendingIntent pi, + MediaSession.TransportControlsCallback listener) { if (pi == null) { Log.w(TAG, "Pending intent was null, can't add rcc listener."); return; } SessionHolder holder = getHolder(pi, true); - TransportPerformer performer = holder.mSession.getTransportPerformer(); if (holder.mRccListener != null) { if (holder.mRccListener == listener) { if (DEBUG) { @@ -92,9 +92,9 @@ public class MediaSessionLegacyHelper { return; } // Otherwise it changed so we need to switch to the new one - performer.removeCallback(holder.mRccListener); + holder.mSession.removeTransportControlsCallback(holder.mRccListener); } - performer.addCallback(listener, mHandler); + holder.mSession.addTransportControlsCallback(listener, mHandler); holder.mRccListener = listener; holder.mFlags |= MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS; holder.mSession.setFlags(holder.mFlags); @@ -110,7 +110,7 @@ public class MediaSessionLegacyHelper { } SessionHolder holder = getHolder(pi, false); if (holder != null && holder.mRccListener != null) { - holder.mSession.getTransportPerformer().removeCallback(holder.mRccListener); + holder.mSession.removeTransportControlsCallback(holder.mRccListener); holder.mRccListener = null; holder.mFlags &= ~MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS; holder.mSession.setFlags(holder.mFlags); @@ -141,7 +141,7 @@ public class MediaSessionLegacyHelper { // set this flag holder.mFlags |= MediaSession.FLAG_HANDLES_MEDIA_BUTTONS; holder.mSession.setFlags(holder.mFlags); - holder.mSession.getTransportPerformer().addCallback(holder.mMediaButtonListener, mHandler); + holder.mSession.addTransportControlsCallback(holder.mMediaButtonListener, mHandler); holder.mMediaButtonReceiver = new MediaButtonReceiver(pi, context); holder.mSession.addCallback(holder.mMediaButtonReceiver, mHandler); @@ -156,7 +156,7 @@ public class MediaSessionLegacyHelper { } SessionHolder holder = getHolder(pi, false); if (holder != null && holder.mMediaButtonListener != null) { - holder.mSession.getTransportPerformer().removeCallback(holder.mMediaButtonListener); + holder.mSession.removeTransportControlsCallback(holder.mMediaButtonListener); holder.mFlags &= ~MediaSession.FLAG_HANDLES_MEDIA_BUTTONS; holder.mSession.setFlags(holder.mFlags); holder.mMediaButtonListener = null; @@ -206,7 +206,7 @@ public class MediaSessionLegacyHelper { } } - private static final class MediaButtonListener extends TransportPerformer.Callback { + private static final class MediaButtonListener extends MediaSession.TransportControlsCallback { private final PendingIntent mPendingIntent; private final Context mContext; @@ -272,7 +272,7 @@ public class MediaSessionLegacyHelper { public final PendingIntent mPi; public MediaButtonListener mMediaButtonListener; public MediaButtonReceiver mMediaButtonReceiver; - public TransportPerformer.Callback mRccListener; + public MediaSession.TransportControlsCallback mRccListener; public int mFlags; public SessionHolder(MediaSession session, PendingIntent pi) { diff --git a/media/java/android/media/session/RemoteVolumeProvider.java b/media/java/android/media/session/RemoteVolumeProvider.java index 2dcf649..47f672f 100644 --- a/media/java/android/media/session/RemoteVolumeProvider.java +++ b/media/java/android/media/session/RemoteVolumeProvider.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package android.media.session; /** @@ -12,23 +27,23 @@ public abstract class RemoteVolumeProvider { * The volume is fixed and can not be modified. Requests to change volume * should be ignored. */ - public static final int VOLUME_CONTROL_FIXED = 1 << 0; + public static final int VOLUME_CONTROL_FIXED = 0; /** * The volume control uses relative adjustment via * {@link #onAdjustVolumeBy(int)}. Attempts to set the volume to a specific * value should be ignored. */ - public static final int VOLUME_CONTROL_RELATIVE = 1 << 1; + public static final int VOLUME_CONTROL_RELATIVE = 1; /** * The volume control uses an absolute value. It may be adjusted using * {@link #onAdjustVolumeBy(int)} or set directly using * {@link #onSetVolumeTo(int)}. */ - public static final int VOLUME_CONTROL_ABSOLUTE = 1 << 2; + public static final int VOLUME_CONTROL_ABSOLUTE = 2; - private final int mFlags; + private final int mControlType; private final int mMaxVolume; /** @@ -40,7 +55,7 @@ public abstract class RemoteVolumeProvider { * @param maxVolume The maximum allowed volume. */ public RemoteVolumeProvider(int volumeControl, int maxVolume) { - mFlags = volumeControl; + mControlType = volumeControl; mMaxVolume = maxVolume; } @@ -52,12 +67,12 @@ public abstract class RemoteVolumeProvider { public abstract int onGetCurrentVolume(); /** - * Get the flags that were set for this volume provider. + * Get the volume control type that this volume provider uses. * - * @return The flags for this volume provider + * @return The volume control type for this volume provider */ - public final int getFlags() { - return mFlags; + public final int getVolumeControl() { + return mControlType; } /** diff --git a/media/java/android/media/session/TransportController.java b/media/java/android/media/session/TransportController.java deleted file mode 100644 index 4bd39ff..0000000 --- a/media/java/android/media/session/TransportController.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.media.session; - -import android.media.MediaMetadata; -import android.media.Rating; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.util.Log; - -import java.util.ArrayList; - -/** - * Interface for controlling media playback on a session. This allows an app to - * request changes in playback, retrieve the current playback state and - * metadata, and listen for changes to the playback state and metadata. - */ -public final class TransportController { - private static final String TAG = "TransportController"; - - private final Object mLock = new Object(); - private final ArrayList mListeners = new ArrayList(); - private final ISessionController mBinder; - - /** - * @hide - */ - public TransportController(ISessionController binder) { - mBinder = binder; - } - - /** - * Start listening to changes in playback state. - */ - public void addStateListener(TransportStateListener listener) { - addStateListener(listener, null); - } - - public void addStateListener(TransportStateListener listener, Handler handler) { - if (listener == null) { - throw new IllegalArgumentException("Listener cannot be null"); - } - synchronized (mLock) { - if (getHandlerForListenerLocked(listener) != null) { - Log.w(TAG, "Listener is already added, ignoring"); - return; - } - if (handler == null) { - handler = new Handler(); - } - - MessageHandler msgHandler = new MessageHandler(handler.getLooper(), listener); - mListeners.add(msgHandler); - } - } - - /** - * Stop listening to changes in playback state. - */ - public void removeStateListener(TransportStateListener listener) { - if (listener == null) { - throw new IllegalArgumentException("Listener cannot be null"); - } - synchronized (mLock) { - removeStateListenerLocked(listener); - } - } - - /** - * Request that the player start its playback at its current position. - */ - public void play() { - try { - mBinder.play(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling play.", e); - } - } - - /** - * Request that the player pause its playback and stay at its current - * position. - */ - public void pause() { - try { - mBinder.pause(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling pause.", e); - } - } - - /** - * Request that the player stop its playback; it may clear its state in - * whatever way is appropriate. - */ - public void stop() { - try { - mBinder.stop(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling stop.", e); - } - } - - /** - * Move to a new location in the media stream. - * - * @param pos Position to move to, in milliseconds. - */ - public void seekTo(long pos) { - try { - mBinder.seekTo(pos); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling seekTo.", e); - } - } - - /** - * Start fast forwarding. If playback is already fast forwarding this may - * increase the rate. - */ - public void fastForward() { - try { - mBinder.fastForward(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling fastForward.", e); - } - } - - /** - * Skip to the next item. - */ - public void skipToNext() { - try { - mBinder.next(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling next.", e); - } - } - - /** - * Start rewinding. If playback is already rewinding this may increase the - * rate. - */ - public void rewind() { - try { - mBinder.rewind(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rewind.", e); - } - } - - /** - * Skip to the previous item. - */ - public void skipToPrevious() { - try { - mBinder.previous(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling previous.", e); - } - } - - /** - * Rate the current content. This will cause the rating to be set for the - * current user. The Rating type must match the type returned by - * {@link #getRatingType()}. - * - * @param rating The rating to set for the current content - */ - public void setRating(Rating rating) { - try { - mBinder.rate(rating); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling rate.", e); - } - } - - /** - * Get the rating type supported by the session. One of: - *

      - *
    • {@link Rating#RATING_NONE}
    • - *
    • {@link Rating#RATING_HEART}
    • - *
    • {@link Rating#RATING_THUMB_UP_DOWN}
    • - *
    • {@link Rating#RATING_3_STARS}
    • - *
    • {@link Rating#RATING_4_STARS}
    • - *
    • {@link Rating#RATING_5_STARS}
    • - *
    • {@link Rating#RATING_PERCENTAGE}
    • - *
    - * - * @return The supported rating type - */ - public int getRatingType() { - try { - return mBinder.getRatingType(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getRatingType.", e); - return Rating.RATING_NONE; - } - } - - /** - * Get the current playback state for this session. - * - * @return The current PlaybackState or null - */ - public PlaybackState getPlaybackState() { - try { - return mBinder.getPlaybackState(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getPlaybackState.", e); - return null; - } - } - - /** - * Get the current metadata for this session. - * - * @return The current MediaMetadata or null. - */ - public MediaMetadata getMetadata() { - try { - return mBinder.getMetadata(); - } catch (RemoteException e) { - Log.wtf(TAG, "Error calling getMetadata.", e); - return null; - } - } - - /** - * @hide - */ - public final void postPlaybackStateChanged(PlaybackState state) { - synchronized (mLock) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).post(MessageHandler.MSG_UPDATE_PLAYBACK_STATE, state); - } - } - } - - /** - * @hide - */ - public final void postMetadataChanged(MediaMetadata metadata) { - synchronized (mLock) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).post(MessageHandler.MSG_UPDATE_METADATA, - metadata); - } - } - } - - private MessageHandler getHandlerForListenerLocked(TransportStateListener listener) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - MessageHandler handler = mListeners.get(i); - if (listener == handler.mListener) { - return handler; - } - } - return null; - } - - private boolean removeStateListenerLocked(TransportStateListener listener) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - if (listener == mListeners.get(i).mListener) { - mListeners.remove(i); - return true; - } - } - return false; - } - - /** - * Register using {@link #addStateListener} to receive updates when there - * are playback changes on the session. - */ - public static abstract class TransportStateListener { - private MessageHandler mHandler; - /** - * Override to handle changes in playback state. - * - * @param state The new playback state of the session - */ - public void onPlaybackStateChanged(PlaybackState state) { - } - - /** - * Override to handle changes to the current metadata. - * - * @see MediaMetadata - * @param metadata The current metadata for the session or null - */ - public void onMetadataChanged(MediaMetadata metadata) { - } - - private void setHandler(Handler handler) { - mHandler = new MessageHandler(handler.getLooper(), this); - } - } - - private static class MessageHandler extends Handler { - private static final int MSG_UPDATE_PLAYBACK_STATE = 1; - private static final int MSG_UPDATE_METADATA = 2; - - private TransportStateListener mListener; - - public MessageHandler(Looper looper, TransportStateListener cb) { - super(looper, null, true); - mListener = cb; - } - - public void post(int msg, Object obj) { - obtainMessage(msg, obj).sendToTarget(); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_PLAYBACK_STATE: - mListener.onPlaybackStateChanged((PlaybackState) msg.obj); - break; - case MSG_UPDATE_METADATA: - mListener.onMetadataChanged((MediaMetadata) msg.obj); - break; - } - } - } - -} diff --git a/media/java/android/media/session/TransportPerformer.java b/media/java/android/media/session/TransportPerformer.java deleted file mode 100644 index 9c4c686..0000000 --- a/media/java/android/media/session/TransportPerformer.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.media.session; - -import android.media.AudioManager; -import android.media.MediaMetadata; -import android.media.Rating; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.util.Log; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -/** - * Allows broadcasting of playback changes. - */ -public final class TransportPerformer { - private static final String TAG = "TransportPerformer"; - private final Object mLock = new Object(); - private final ArrayList mCallbacks = new ArrayList(); - - private ISession mBinder; - - /** - * @hide - */ - public TransportPerformer(ISession binder) { - mBinder = binder; - } - - /** - * Add a callback to receive updates on. - * - * @param callback The callback object - */ - public void addCallback(Callback callback) { - addCallback(callback, null); - } - - /** - * Add a callback to receive updates on. The updates will be posted to the - * specified handler. If no handler is provided they will be posted to the - * caller's thread. - * - * @param callback The callback to receive updates on - * @param handler The handler to post the updates on - */ - public void addCallback(Callback callback, Handler handler) { - if (callback == null) { - throw new IllegalArgumentException("Callback cannot be null"); - } - synchronized (mLock) { - if (getHandlerForCallbackLocked(callback) != null) { - Log.w(TAG, "Callback is already added, ignoring"); - } - if (handler == null) { - handler = new Handler(); - } - MessageHandler msgHandler = new MessageHandler(handler.getLooper(), callback); - mCallbacks.add(msgHandler); - } - } - - /** - * Stop receiving updates on the specified handler. If an update has already - * been posted you may still receive it after this call returns. - * - * @param callback The callback to stop receiving updates on - */ - public void removeCallback(Callback callback) { - if (callback == null) { - throw new IllegalArgumentException("Callback cannot be null"); - } - synchronized (mLock) { - removeCallbackLocked(callback); - } - } - - /** - * Update the current playback state. - * - * @param state The current state of playback - */ - public void setPlaybackState(PlaybackState state) { - try { - mBinder.setPlaybackState(state); - } catch (RemoteException e) { - Log.wtf(TAG, "Dead object in setPlaybackState.", e); - } - } - - /** - * Update the current metadata. New metadata can be created using - * {@link MediaMetadata.Builder}. - * - * @param metadata The new metadata - */ - public void setMetadata(MediaMetadata metadata) { - try { - mBinder.setMetadata(metadata); - } catch (RemoteException e) { - Log.wtf(TAG, "Dead object in setPlaybackState.", e); - } - } - - /** - * @hide - */ - public void dispatchPlay() { - post(MessageHandler.MESSAGE_PLAY); - } - - /** - * @hide - */ - public void dispatchPause() { - post(MessageHandler.MESSAGE_PAUSE); - } - - /** - * @hide - */ - public void dispatchStop() { - post(MessageHandler.MESSAGE_STOP); - } - - /** - * @hide - */ - public void dispatchNext() { - post(MessageHandler.MESSAGE_NEXT); - } - - /** - * @hide - */ - public void dispatchPrevious() { - post(MessageHandler.MESSAGE_PREVIOUS); - } - - /** - * @hide - */ - public void dispatchFastForward() { - post(MessageHandler.MESSAGE_FAST_FORWARD); - } - - /** - * @hide - */ - public void dispatchRewind() { - post(MessageHandler.MESSAGE_REWIND); - } - - /** - * @hide - */ - public void dispatchSeekTo(long pos) { - post(MessageHandler.MESSAGE_SEEK_TO, pos); - } - - /** - * @hide - */ - public void dispatchRate(Rating rating) { - post(MessageHandler.MESSAGE_RATE, rating); - } - - private MessageHandler getHandlerForCallbackLocked(Callback callback) { - for (int i = mCallbacks.size() - 1; i >= 0; i--) { - MessageHandler handler = mCallbacks.get(i); - if (callback == handler.mCallback) { - return handler; - } - } - return null; - } - - private boolean removeCallbackLocked(Callback callback) { - for (int i = mCallbacks.size() - 1; i >= 0; i--) { - if (callback == mCallbacks.get(i).mCallback) { - mCallbacks.remove(i); - return true; - } - } - return false; - } - - private void post(int what, Object obj) { - synchronized (mLock) { - for (int i = mCallbacks.size() - 1; i >= 0; i--) { - mCallbacks.get(i).post(what, obj); - } - } - } - - private void post(int what) { - post(what, null); - } - - /** - * Extend to handle transport controls. Callbacks can be registered using - * {@link #addCallback}. - */ - public static abstract class Callback { - - /** - * Override to handle requests to begin playback. - */ - public void onPlay() { - } - - /** - * Override to handle requests to pause playback. - */ - public void onPause() { - } - - /** - * Override to handle requests to skip to the next media item. - */ - public void onSkipToNext() { - } - - /** - * Override to handle requests to skip to the previous media item. - */ - public void onSkipToPrevious() { - } - - /** - * Override to handle requests to fast forward. - */ - public void onFastForward() { - } - - /** - * Override to handle requests to rewind. - */ - public void onRewind() { - } - - /** - * Override to handle requests to stop playback. - */ - public void onStop() { - } - - /** - * Override to handle requests to seek to a specific position in ms. - * - * @param pos New position to move to, in milliseconds. - */ - public void onSeekTo(long pos) { - } - - /** - * Override to handle the item being rated. - * - * @param rating - */ - public void onSetRating(Rating rating) { - } - - /** - * Report that audio focus has changed on the app. This only happens if - * you have indicated you have started playing with - * {@link #setPlaybackState}. - * - * @param focusChange The type of focus change, TBD. - * @hide - */ - public void onRouteFocusChange(int focusChange) { - } - } - - private class MessageHandler extends Handler { - private static final int MESSAGE_PLAY = 1; - private static final int MESSAGE_PAUSE = 2; - private static final int MESSAGE_STOP = 3; - private static final int MESSAGE_NEXT = 4; - private static final int MESSAGE_PREVIOUS = 5; - private static final int MESSAGE_FAST_FORWARD = 6; - private static final int MESSAGE_REWIND = 7; - private static final int MESSAGE_SEEK_TO = 8; - private static final int MESSAGE_RATE = 9; - - private TransportPerformer.Callback mCallback; - - public MessageHandler(Looper looper, TransportPerformer.Callback cb) { - super(looper); - mCallback = cb; - } - - public void post(int what, Object obj) { - obtainMessage(what, obj).sendToTarget(); - } - - public void post(int what) { - post(what, null); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_PLAY: - mCallback.onPlay(); - break; - case MESSAGE_PAUSE: - mCallback.onPause(); - break; - case MESSAGE_STOP: - mCallback.onStop(); - break; - case MESSAGE_NEXT: - mCallback.onSkipToNext(); - break; - case MESSAGE_PREVIOUS: - mCallback.onSkipToPrevious(); - break; - case MESSAGE_FAST_FORWARD: - mCallback.onFastForward(); - break; - case MESSAGE_REWIND: - mCallback.onRewind(); - break; - case MESSAGE_SEEK_TO: - mCallback.onSeekTo((Long) msg.obj); - break; - case MESSAGE_RATE: - mCallback.onSetRating((Rating) msg.obj); - break; - } - } - } -} diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java index 9f7bb26..145b389 100644 --- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java +++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java @@ -21,7 +21,6 @@ import android.media.session.MediaController; import android.media.session.RouteInfo; import android.media.session.MediaSessionManager; import android.media.session.PlaybackState; -import android.media.session.TransportController; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -42,12 +41,11 @@ public class PlayerController { protected MediaController mController; protected IPlayerService mBinder; - protected TransportController mTransportControls; + protected MediaController.TransportControls mTransportControls; private final Intent mServiceIntent; private Context mContext; private Listener mListener; - private TransportListener mTransportListener = new TransportListener(); private SessionCallback mControllerCb; private MediaSessionManager mManager; private Handler mHandler = new Handler(); @@ -161,16 +159,13 @@ public class PlayerController { return; } mController.addCallback(mControllerCb, mHandler); - mTransportControls = mController.getTransportController(); - if (mTransportControls != null) { - mTransportControls.addStateListener(mTransportListener); - } + mTransportControls = mController.getTransportControls(); Log.d(TAG, "Ready to use PlayerService"); if (mListener != null) { mListener.onConnectionStateChange(STATE_CONNECTED); if (mTransportControls != null) { - mListener.onPlaybackStateChange(mTransportControls.getPlaybackState()); + mListener.onPlaybackStateChange(mController.getPlaybackState()); } } } @@ -181,9 +176,7 @@ public class PlayerController { public void onRouteChanged(RouteInfo route) { // TODO } - } - private class TransportListener extends TransportController.TransportStateListener { @Override public void onPlaybackStateChanged(PlaybackState state) { if (state == null) { diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java index 97a0a08..c1fa74f 100644 --- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java +++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java @@ -25,7 +25,6 @@ import android.media.session.MediaSession; import android.media.session.MediaSessionManager; import android.media.session.MediaSessionToken; import android.media.session.PlaybackState; -import android.media.session.TransportPerformer; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; @@ -45,7 +44,6 @@ public class PlayerSession { protected Renderer mRenderer; protected MediaSession.Callback mCallback; protected Renderer.Listener mRenderListener; - protected TransportPerformer mPerformer; protected PlaybackState mPlaybackState; protected Listener mListener; @@ -84,9 +82,8 @@ public class PlayerSession { Log.d(TAG, "Creating session for package " + mContext.getBasePackageName()); mSession = man.createSession("OneMedia"); mSession.addCallback(mCallback); - mPerformer = mSession.getTransportPerformer(); - mPerformer.addCallback(new TransportListener()); - mPerformer.setPlaybackState(mPlaybackState); + mSession.addTransportControlsCallback(new TransportListener()); + mSession.setPlaybackState(mPlaybackState); mSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS); mSession.setRouteOptions(mRouteOptions); mSession.setActive(true); @@ -123,7 +120,7 @@ public class PlayerSession { float rate = newState == PlaybackState.STATE_PLAYING ? 1 : 0; long position = mRenderer == null ? -1 : mRenderer.getSeekPosition(); mPlaybackState.setState(newState, position, rate); - mPerformer.setPlaybackState(mPlaybackState); + mSession.setPlaybackState(mPlaybackState); } public interface Listener { @@ -139,7 +136,7 @@ public class PlayerSession { if (error != null) { mPlaybackState.setErrorMessage(error.getLocalizedMessage()); } - mPerformer.setPlaybackState(mPlaybackState); + mSession.setPlaybackState(mPlaybackState); if (mListener != null) { mListener.onPlayStateChanged(mPlaybackState); } @@ -177,7 +174,7 @@ public class PlayerSession { mPlaybackState.setErrorMessage("unkown state"); break; } - mPerformer.setPlaybackState(mPlaybackState); + mSession.setPlaybackState(mPlaybackState); if (mListener != null) { mListener.onPlayStateChanged(mPlaybackState); } @@ -192,7 +189,7 @@ public class PlayerSession { Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED); long position = mRenderer == null ? -1 : mRenderer.getSeekPosition(); mPlaybackState.setState(PlaybackState.STATE_PAUSED, position, 0); - mPerformer.setPlaybackState(mPlaybackState); + mSession.setPlaybackState(mPlaybackState); if (mListener != null) { mListener.onPlayStateChanged(mPlaybackState); } @@ -258,7 +255,7 @@ public class PlayerSession { } } - private class TransportListener extends TransportPerformer.Callback { + private class TransportListener extends MediaSession.TransportControlsCallback { @Override public void onPlay() { mRenderer.onPlay(); -- cgit v1.1