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

Commit 0d61a00c authored by Jaewan Kim's avatar Jaewan Kim
Browse files

MediaSession2: Add/remove playback listeners

Test: Run all MediaComponents test once
Change-Id: If88fa492d40f9d202e8bdfcebd06cd9b82554041
parent f7a7706d
Loading
Loading
Loading
Loading
+6 −27
Original line number Original line Diff line number Diff line
@@ -24,9 +24,7 @@ import android.os.Bundle;
 *
 *
 * @hide
 * @hide
 */
 */
// TODO(jaewan): Make this oneway interface.
oneway interface IMediaSession2 {
//               Malicious app can fake session binder and holds commands from controller.
interface IMediaSession2 {
    // TODO(jaewan): add onCommand() to send private command
    // TODO(jaewan): add onCommand() to send private command
    // TODO(jaewan): Due to the nature of oneway calls, APIs can be called in out of order
    // TODO(jaewan): Due to the nature of oneway calls, APIs can be called in out of order
    //               Add id for individual calls to address this.
    //               Add id for individual calls to address this.
@@ -35,37 +33,18 @@ interface IMediaSession2 {
    //               not to expose other methods to the controller whose connection wasn't accepted.
    //               not to expose other methods to the controller whose connection wasn't accepted.
    //               But this would be enough for now because it's the same as existing
    //               But this would be enough for now because it's the same as existing
    //               MediaBrowser and MediaBrowserService.
    //               MediaBrowser and MediaBrowserService.
    oneway void connect(String callingPackage, IMediaSession2Callback callback);
    void connect(String callingPackage, IMediaSession2Callback callback);
    oneway void release(IMediaSession2Callback caller);
    void release(IMediaSession2Callback caller);


    //////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////
    // send command
    // send command
    //////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////
    oneway void sendCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args);
    void sendCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args);
    oneway void sendTransportControlCommand(IMediaSession2Callback caller,
    void sendTransportControlCommand(IMediaSession2Callback caller,
            int commandCode, long arg);
            int commandCode, long arg);


    Bundle getPlaybackState();

    //////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////
    // Get library service specific
    // Get library service specific
    //////////////////////////////////////////////////////////////////////////////////////////////
    //////////////////////////////////////////////////////////////////////////////////////////////
    oneway void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
    void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);

    //////////////////////////////////////////////////////////////////////////////////////////////
    // Callbacks -- remove them
    //////////////////////////////////////////////////////////////////////////////////////////////
    /**
     * @param callbackBinder binder to be used to notify changes.
     * @param callbackFlag one of {@link MediaController2#FLAG_CALLBACK_PLAYBACK} or
     *     {@link MediaController2#FLAG_CALLBACK_SESSION_ACTIVENESS}
     * @param requestCode If >= 0, this code will be called back by the callback after the callback
     *     is registered.
     */
    // TODO(jaewan): Due to the nature of the binder, calls can be called out of order.
    //               Need a way to ensure calling of unregisterCallback unregisters later
    //               registerCallback.
    oneway void registerCallback(IMediaSession2Callback callbackBinder,
            int callbackFlag, int requestCode);
    oneway void unregisterCallback(IMediaSession2Callback callbackBinder, int callbackFlag);
}
}
+9 −5
Original line number Original line Diff line number Diff line
@@ -133,9 +133,9 @@ public class MediaController2 implements AutoCloseable {
                @NonNull List<MediaItem2> list, @NonNull PlaylistParams param) { }
                @NonNull List<MediaItem2> list, @NonNull PlaylistParams param) { }


        /**
        /**
         * Called when the playback state is changed.
         * Called when the playback state is changed, or connection success.
         *
         *
         * @param state
         * @param state latest playback state
         */
         */
        public void onPlaybackStateChanged(@NonNull PlaybackState2 state) { }
        public void onPlaybackStateChanged(@NonNull PlaybackState2 state) { }


@@ -546,11 +546,15 @@ public class MediaController2 implements AutoCloseable {
    }
    }


    /**
    /**
     * Get the latest {@link PlaybackState2} from the session.
     * Get the lastly cached {@link PlaybackState2} from
     * {@link ControllerCallback#onPlaybackStateChanged(PlaybackState2)}.
     * <p>
     * It may return {@code null} before the first callback or session has sent {@code null}
     * playback state.
     *
     *
     * @return a playback state
     * @return a playback state. Can be {@code null}
     */
     */
    public PlaybackState2 getPlaybackState() {
    public @Nullable PlaybackState2 getPlaybackState() {
        return mProvider.getPlaybackState_impl();
        return mProvider.getPlaybackState_impl();
    }
    }


+37 −2
Original line number Original line Diff line number Diff line
@@ -83,6 +83,7 @@ public class MediaSession2 implements AutoCloseable {


    // Note: Do not define IntDef because subclass can add more command code on top of these.
    // Note: Do not define IntDef because subclass can add more command code on top of these.
    // TODO(jaewan): Shouldn't we pull out?
    // TODO(jaewan): Shouldn't we pull out?
    // TODO(jaewan): Should we also protect getPlaybackState()?
    public static final int COMMAND_CODE_CUSTOM = 0;
    public static final int COMMAND_CODE_CUSTOM = 0;
    public static final int COMMAND_CODE_PLAYBACK_START = 1;
    public static final int COMMAND_CODE_PLAYBACK_START = 1;
    public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2;
    public static final int COMMAND_CODE_PLAYBACK_PAUSE = 2;
@@ -199,7 +200,8 @@ public class MediaSession2 implements AutoCloseable {
        @Override
        @Override
        public int hashCode() {
        public int hashCode() {
            final int prime = 31;
            final int prime = 31;
            return ((mCustomCommand != null) ? mCustomCommand.hashCode() : 0) * prime + mCommandCode;
            return ((mCustomCommand != null)
                    ? mCustomCommand.hashCode() : 0) * prime + mCommandCode;
        }
        }
    }
    }


@@ -999,7 +1001,6 @@ public class MediaSession2 implements AutoCloseable {
     *       framework had to add heuristics to figure out if an app is
     *       framework had to add heuristics to figure out if an app is
     * @hide
     * @hide
     */
     */

    MediaSession2(Context context, MediaPlayerInterface player, String id,
    MediaSession2(Context context, MediaPlayerInterface player, String id,
            VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
            VolumeProvider volumeProvider, int ratingType, PendingIntent sessionActivity,
            Executor callbackExecutor, SessionCallback callback) {
            Executor callbackExecutor, SessionCallback callback) {
@@ -1288,4 +1289,38 @@ public class MediaSession2 implements AutoCloseable {
    public PlaylistParams getPlaylistParams() {
    public PlaylistParams getPlaylistParams() {
        return mProvider.getPlaylistParams_impl();
        return mProvider.getPlaylistParams_impl();
    }
    }

    /*
     * Add a {@link PlaybackListener} to listen changes in the underlying
     * {@link MediaPlayerInterface}. Listener will be called immediately to tell the current value.
     * <p>
     * Added listeners will be also called when the underlying player is changed.
     *
     * @param executor the call listener
     * @param listener the listener that will be run
     * @throws IllegalArgumentException when either the listener or handler is {@code null}.
     */
    public void addPlaybackListener(@NonNull @CallbackExecutor Executor executor,
            @NonNull PlaybackListener listener) {
        mProvider.addPlaybackListener_impl(executor, listener);
    }

    /**
     * Remove previously added {@link PlaybackListener}.
     *
     * @param listener the listener to be removed
     * @throws IllegalArgumentException if the listener is {@code null}.
     */
    public void removePlaybackListener(@NonNull PlaybackListener listener) {
        mProvider.removePlaybackListener_impl(listener);
    }

    /**
     * Return the {@link PlaybackState2} from the player.
     *
     * @return playback state
     */
    public PlaybackState2 getPlaybackState() {
        return mProvider.getPlaybackState_impl();
    }
}
}
+3 −0
Original line number Original line Diff line number Diff line
@@ -108,6 +108,9 @@ public final class PlaybackState2 {
    private final long mActiveItemId;
    private final long mActiveItemId;
    private final CharSequence mErrorMessage;
    private final CharSequence mErrorMessage;


    // TODO(jaewan): Better error handling?
    //               E.g. media item at #2 has issue, but continue playing #3
    //                    login error. fire intent xxx to login
    public PlaybackState2(int state, long position, long updateTime, float speed,
    public PlaybackState2(int state, long position, long updateTime, float speed,
            long bufferedPosition, long activeItemId, CharSequence error) {
            long bufferedPosition, long activeItemId, CharSequence error) {
        mState = state;
        mState = state;
+5 −0
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package android.media.update;
import android.media.AudioAttributes;
import android.media.AudioAttributes;
import android.media.MediaItem2;
import android.media.MediaItem2;
import android.media.MediaPlayerInterface;
import android.media.MediaPlayerInterface;
import android.media.MediaPlayerInterface.PlaybackListener;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.Command;
import android.media.MediaSession2.CommandButton;
import android.media.MediaSession2.CommandButton;
import android.media.MediaSession2.CommandGroup;
import android.media.MediaSession2.CommandGroup;
@@ -30,6 +31,7 @@ import android.os.Bundle;
import android.os.ResultReceiver;
import android.os.ResultReceiver;


import java.util.List;
import java.util.List;
import java.util.concurrent.Executor;


/**
/**
 * @hide
 * @hide
@@ -56,6 +58,9 @@ public interface MediaSession2Provider extends TransportControlProvider {
    void setPlaylistParams_impl(PlaylistParams params);
    void setPlaylistParams_impl(PlaylistParams params);
    PlaylistParams getPlaylistParams_impl();
    PlaylistParams getPlaylistParams_impl();


    void addPlaybackListener_impl(Executor executor, PlaybackListener listener);
    void removePlaybackListener_impl(PlaybackListener listener);

    interface ControllerInfoProvider {
    interface ControllerInfoProvider {
        String getPackageName_impl();
        String getPackageName_impl();
        int getUid_impl();
        int getUid_impl();
Loading