Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c47fa84b authored by RoboErik's avatar RoboErik
Browse files

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
parent 79fa4630
Loading
Loading
Loading
Loading
+40 −51
Original line number Diff line number Diff line
@@ -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
  }
}
+5 −5
Original line number Diff line number Diff line
@@ -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) {
+210 −31
Original line number Diff line number Diff line
@@ -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,11 +117,62 @@ 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:
     * <ul>
     * <li>{@link Rating#RATING_NONE}</li>
     * <li>{@link Rating#RATING_HEART}</li>
     * <li>{@link Rating#RATING_THUMB_UP_DOWN}</li>
     * <li>{@link Rating#RATING_3_STARS}</li>
     * <li>{@link Rating#RATING_4_STARS}</li>
     * <li>{@link Rating#RATING_5_STARS}</li>
     * <li>{@link Rating#RATING_PERCENTAGE}</li>
     * </ul>
     *
     * @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;
            }
        }

+329 −77

File changed.

Preview size limit exceeded, changes collapsed.

+9 −9
Original line number Diff line number Diff line
@@ -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) {
Loading