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

Commit c3a438f6 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

MediaPlayerBase API

Define as an abstract class the high level interface for
  media players. Consumers are MediaSession2, providers
  are MediaPlayer2, which will extend this class.

Bug: 64098437
Test: to be in MediaPlayer2 tests once it extends MPB
Change-Id: Id0d0fcb6d1b377a0e05a4a8e3d659e12a58fc45e
parent f3f5c320
Loading
Loading
Loading
Loading
+51 −6
Original line number Diff line number Diff line
@@ -23339,7 +23339,7 @@ package android.media {
    field public static final int REGULAR_CODECS = 0; // 0x0
  }
  public class MediaController2 implements java.lang.AutoCloseable {
  public class MediaController2 implements java.lang.AutoCloseable android.media.MediaPlaylistController {
    ctor public MediaController2(android.content.Context, android.media.SessionToken2, java.util.concurrent.Executor, android.media.MediaController2.ControllerCallback);
    method public void addPlaylistItem(int, android.media.MediaItem2);
    method public void adjustVolume(int, int);
@@ -23366,6 +23366,7 @@ package android.media {
    method public void prepareFromSearch(java.lang.String, android.os.Bundle);
    method public void prepareFromUri(android.net.Uri, android.os.Bundle);
    method public void removePlaylistItem(android.media.MediaItem2);
    method public void replacePlaylistItem(int, android.media.MediaItem2);
    method public void rewind();
    method public void seekTo(long);
    method public void sendCustomCommand(android.media.MediaSession2.Command, android.os.Bundle, android.os.ResultReceiver);
@@ -24466,14 +24467,56 @@ package android.media {
  public abstract class MediaPlayerBase implements java.lang.AutoCloseable {
    ctor public MediaPlayerBase();
    method public abstract android.media.AudioAttributes getAudioAttributes();
    method public long getBufferedPosition();
    method public abstract int getBufferingState();
    method public abstract android.media.DataSourceDesc getCurrentDataSource();
    method public long getCurrentPosition();
    method public long getDuration();
    method public float getMaxPlayerVolume();
    method public float getPlaybackSpeed();
    method public abstract int getPlayerState();
    method public abstract float getPlayerVolume();
    method public boolean isReversePlaybackSupported();
    method public abstract void loopCurrent(boolean);
    method public abstract void pause();
    method public abstract void play();
    method public abstract void prepare();
    method public abstract void registerPlayerEventCallback(java.util.concurrent.Executor, android.media.MediaPlayerBase.PlayerEventCallback);
    method public abstract void seekTo(long);
    method public abstract void setAudioAttributes(android.media.AudioAttributes);
    field public static final int STATE_ERROR = 0; // 0x0
    field public static final int STATE_IDLE = 0; // 0x0
    field public static final int STATE_PAUSED = 0; // 0x0
    field public static final int STATE_PLAYING = 0; // 0x0
    method public abstract void setDataSource(android.media.DataSourceDesc);
    method public abstract void setNextDataSource(android.media.DataSourceDesc);
    method public abstract void setNextDataSources(java.util.List<android.media.DataSourceDesc>);
    method public abstract void setPlaybackSpeed(float);
    method public abstract void setVolume(float);
    method public abstract void skipToNext();
    method public abstract void unregisterPlayerEventCallback(android.media.MediaPlayerBase.PlayerEventCallback);
    field public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1; // 0x1
    field public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2; // 0x2
    field public static final int BUFFERING_STATE_BUFFERING_COMPLETE = 3; // 0x3
    field public static final int BUFFERING_STATE_UNKNOWN = 0; // 0x0
    field public static final int PLAYER_STATE_ERROR = 3; // 0x3
    field public static final int PLAYER_STATE_IDLE = 0; // 0x0
    field public static final int PLAYER_STATE_PAUSED = 1; // 0x1
    field public static final int PLAYER_STATE_PLAYING = 2; // 0x2
    field public static final long UNKNOWN_TIME = -1L; // 0xffffffffffffffffL
  }
  public static abstract class MediaPlayerBase.PlayerEventCallback {
    ctor public MediaPlayerBase.PlayerEventCallback();
    method public void onBufferingStateChanged(android.media.MediaPlayerBase, android.media.DataSourceDesc, int);
    method public void onCurrentDataSourceChanged(android.media.MediaPlayerBase, android.media.DataSourceDesc);
    method public void onMediaPrepared(android.media.MediaPlayerBase, android.media.DataSourceDesc);
    method public void onPlayerStateChanged(android.media.MediaPlayerBase, int);
  }
  public abstract interface MediaPlaylistController {
    method public abstract void addPlaylistItem(int, android.media.MediaItem2);
    method public abstract android.media.MediaItem2 getCurrentPlaylistItem();
    method public abstract java.util.List<android.media.MediaItem2> getPlaylist();
    method public abstract void removePlaylistItem(android.media.MediaItem2);
    method public abstract void replacePlaylistItem(int, android.media.MediaItem2);
    method public abstract void skipToPlaylistItem(android.media.MediaItem2);
  }
  public class MediaRecorder implements android.media.AudioRouting {
@@ -24752,7 +24795,7 @@ package android.media {
    method public abstract void onScanCompleted(java.lang.String, android.net.Uri);
  }
  public class MediaSession2 implements java.lang.AutoCloseable {
  public class MediaSession2 implements java.lang.AutoCloseable android.media.MediaPlaylistController {
    method public void addPlaylistItem(int, android.media.MediaItem2);
    method public void close();
    method public void editPlaylistItem(android.media.MediaItem2);
@@ -24768,6 +24811,7 @@ package android.media {
    method public void play();
    method public void prepare();
    method public void removePlaylistItem(android.media.MediaItem2);
    method public void replacePlaylistItem(int, android.media.MediaItem2);
    method public void rewind();
    method public void seekTo(long);
    method public void sendCustomCommand(android.media.MediaSession2.Command, android.os.Bundle);
@@ -24822,6 +24866,7 @@ package android.media {
  public static final class MediaSession2.Builder {
    ctor public MediaSession2.Builder(android.content.Context, android.media.MediaPlayerBase);
    ctor public MediaSession2.Builder(android.content.Context, android.media.MediaPlayerBase, android.media.MediaPlaylistController);
    method public android.media.MediaSession2 build();
    method public android.media.MediaSession2.Builder setId(java.lang.String);
    method public android.media.MediaSession2.Builder setSessionActivity(android.app.PendingIntent);
+15 −8
Original line number Diff line number Diff line
@@ -371,7 +371,7 @@ public class MediaController2 implements AutoCloseable, MediaPlaylistController
     * Request that the player prepare its playback. In other words, other sessions can continue
     * to play during the preparation of this session. This method can be used to speed up the
     * start of the playback. Once the preparation is done, the session will change its playback
     * state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards, {@link #play} can be called to
     * state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards, {@link #play} can be called to
     * start playback.
     */
    public void prepare() {
@@ -479,7 +479,7 @@ public class MediaController2 implements AutoCloseable, MediaPlaylistController
     * Request that the player prepare playback for a specific media id. In other words, other
     * sessions can continue to play during the preparation of this session. This method can be
     * used to speed up the start of the playback. Once the preparation is done, the session
     * will change its playback state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards,
     * will change its playback state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards,
     * {@link #play} can be called to start playback. If the preparation is not needed,
     * {@link #playFromMediaId} can be directly called without this method.
     *
@@ -496,7 +496,7 @@ public class MediaController2 implements AutoCloseable, MediaPlaylistController
     * query should be treated as a request to prepare any music. In other words, other sessions
     * can continue to play during the preparation of this session. This method can be used to
     * speed up the start of the playback. Once the preparation is done, the session will
     * change its playback state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards,
     * change its playback state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards,
     * {@link #play} can be called to start playback. If the preparation is not needed,
     * {@link #playFromSearch} can be directly called without this method.
     *
@@ -512,7 +512,7 @@ public class MediaController2 implements AutoCloseable, MediaPlaylistController
     * Request that the player prepare playback for a specific {@link Uri}. In other words,
     * other sessions can continue to play during the preparation of this session. This method
     * can be used to speed up the start of the playback. Once the preparation is done, the
     * session will change its playback state to {@link MediaPlayerBase#STATE_PAUSED}. Afterwards,
     * session will change its playback state to {@link MediaPlayerBase#PLAYER_STATE_PAUSED}. Afterwards,
     * {@link #play} can be called to start playback. If the preparation is not needed,
     * {@link #playFromUri} can be directly called without this method.
     *
@@ -702,15 +702,22 @@ public class MediaController2 implements AutoCloseable, MediaPlaylistController
     *<p>
     * If index is same as the current index of the playlist, current playback
     * will be stopped and playback moves to next source in the list.
     *
     * @throws IllegalArgumentException if the play list is null
     * @throws IndexOutOfBoundsException if index is outside play list range
     */
    @Override
    public void removePlaylistItem(@NonNull MediaItem2 item) {
        mProvider.removePlaylistItem_impl(item);
    }

    /**
     * Replace the media item at index in the playlist.
     * @param index the index of the item to replace
     * @param item the new item
     */
    @Override
    public void replacePlaylistItem(int index, @NonNull MediaItem2 item) {
        mProvider.replacePlaylistItem_impl(index, item);
    }

    /**
     * Inserts the media item to the play list at position index.
     * <p>
+168 −105
Original line number Diff line number Diff line
@@ -34,214 +34,277 @@ public abstract class MediaPlayerBase implements AutoCloseable {
    /**
     * @hide
     */
    @IntDef({STATE_IDLE, STATE_PAUSED, STATE_PLAYING, STATE_ERROR})
    @IntDef({
        PLAYER_STATE_IDLE,
        PLAYER_STATE_PAUSED,
        PLAYER_STATE_PLAYING,
        PLAYER_STATE_ERROR })
    @Retention(RetentionPolicy.SOURCE)
    public @interface State {}
    public @interface PlayerState {}

    /**
     * @hide
     */
    @IntDef({
        BUFFERING_STATE_UNKNOWN,
        BUFFERING_STATE_BUFFERING_AND_PLAYABLE,
        BUFFERING_STATE_BUFFERING_AND_STARVED,
        BUFFERING_STATE_BUFFERING_COMPLETE })
    @Retention(RetentionPolicy.SOURCE)
    public @interface BuffState {}

    /**
     * State when the player is idle, and needs configuration to start playback.
     */
    public static final int STATE_IDLE = 0;
    public static final int PLAYER_STATE_IDLE = 0;

    /**
     * State when the player's playback is paused
     */
    public static final int STATE_PAUSED = 0;
    public static final int PLAYER_STATE_PAUSED = 1;

    /**
     * State when the player's playback is ongoing
     */
    public static final int STATE_PLAYING = 0;
    public static final int PLAYER_STATE_PLAYING = 2;

    /**
     * State when the player is in error state and cannot be recovered self.
     */
    public static final int STATE_ERROR = 0;
    public static final int PLAYER_STATE_ERROR = 3;

    /**
     * Unspecified media player error.
     * @hide
     * Buffering state is unknown.
     */
    public static final int MEDIA_ERROR_UNKNOWN = MediaPlayer2.MEDIA_ERROR_UNKNOWN;
    public static final int BUFFERING_STATE_UNKNOWN = 0;

    /**
     * The video is streamed and its container is not valid for progressive
     * playback i.e the video's index (e.g moov atom) is not at the start of the
     * file.
     * @hide
     * Buffering state indicating the player is buffering but enough has been buffered
     * for this player to be able to play the content.
     * See {@link #getBufferedPosition()} for how far is buffered already.
     */
    public static final int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK =
            MediaPlayer2.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK;
    public static final int BUFFERING_STATE_BUFFERING_AND_PLAYABLE = 1;

    /**
     * File or network related operation errors.
     * @hide
     * Buffering state indicating the player is buffering, but the player is currently starved
     * for data, and cannot play.
     */
    public static final int MEDIA_ERROR_IO = MediaPlayer2.MEDIA_ERROR_IO;
    public static final int BUFFERING_STATE_BUFFERING_AND_STARVED = 2;

    /**
     * Bitstream is not conforming to the related coding standard or file spec.
     * @hide
     * Buffering state indicating the player is done buffering, and the remainder of the content is
     * available for playback.
     */
    public static final int MEDIA_ERROR_MALFORMED = MediaPlayer2.MEDIA_ERROR_MALFORMED;
    public static final int BUFFERING_STATE_BUFFERING_COMPLETE = 3;

    /**
     * Bitstream is conforming to the related coding standard or file spec, but
     * the media framework does not support the feature.
     * @hide
     * Starts or resumes playback.
     */
    public static final int MEDIA_ERROR_UNSUPPORTED = MediaPlayer2.MEDIA_ERROR_UNSUPPORTED;
    public abstract void play();

    /**
     * Some operation takes too long to complete, usually more than 3-5 seconds.
     * @hide
     * Prepares the player for playback.
     * See {@link PlayerEventCallback#onMediaPrepared(MediaPlayerBase, DataSourceDesc)} for being
     * notified when the preparation phase completed. During this time, the player may allocate
     * resources required to play, such as audio and video decoders.
     */
    public static final int MEDIA_ERROR_TIMED_OUT = MediaPlayer2.MEDIA_ERROR_TIMED_OUT;
    public abstract void prepare();

    /**
     * Callbacks to listens to the changes in {@link PlaybackState2} and error.
     * @hide
     * Pauses playback.
     */
    public static abstract class EventCallback {
    public abstract void pause();

    /**
         * Called when {@link PlaybackState2} for this player is changed.
     *
     */
        public void onPlaybackStateChanged(PlaybackState2 state) { }
    public abstract void skipToNext();

    /**
         * Called to indicate an error.
         *
         * @param mediaId optional mediaId to indicate error
         * @param what what
         * @param extra
     * Moves the playback head to the specified position
     * @param pos the new playback position expressed in ms.
     */
        public void onError(@Nullable String mediaId, int what, int extra) { }
    }
    public abstract void seekTo(long pos);

    public static final long UNKNOWN_TIME = -1;

    // Transport controls that session will send command directly to this player.
    /**
     * Start or resumes playback
     * Returns the current playback head position.
     * @return the current play position in ms, or {@link #UNKNOWN_TIME} if unknown.
     */
    public abstract void play();
    public long getCurrentPosition() { return UNKNOWN_TIME; }

    /**
     * @hide
     * Returns the duration of the current data source, or {@link #UNKNOWN_TIME} if unknown.
     * @return the duration in ms, or {@link #UNKNOWN_TIME}.
     */
    public abstract void prepare();
    public long getDuration() { return UNKNOWN_TIME; }

    /**
     * Pause playback
     * Returns the duration of the current data source, or {@link #UNKNOWN_TIME} if unknown.
     * @return the duration in ms, or {@link #UNKNOWN_TIME}.
     */
    public abstract void pause();
    public long getBufferedPosition() { return UNKNOWN_TIME; }

    /**
     * @hide
     * Returns the current player state.
     * See also {@link PlayerEventCallback#onPlayerStateChanged(MediaPlayerBase, int)} for
     * notification of changes.
     * @return the current player state
     */
    public abstract void stop();
    public abstract @PlayerState int getPlayerState();

    /**
     * @hide
     * Returns the current buffering state of the player.
     * During buffering, see {@link #getBufferedPosition()} for the quantifying the amount already
     * buffered.
     * @return the buffering state.
     */
    public abstract void skipToPrevious();
    public abstract @BuffState int getBufferingState();

    /**
     * @hide
     * Sets the {@link AudioAttributes} to be used during the playback of the media.
     *
     * @param attributes non-null <code>AudioAttributes</code>.
     */
    public abstract void skipToNext();
    public abstract void setAudioAttributes(@NonNull AudioAttributes attributes);

    /**
     * @hide
     * Returns AudioAttributes that media player has.
     */
    public abstract void seekTo(long pos);
    public abstract @Nullable AudioAttributes getAudioAttributes();

    /**
     * @hide
     * Sets the data source to be played.
     * @param dsd
     */
    public abstract void fastForward();
    public abstract void setDataSource(@NonNull DataSourceDesc dsd);

    /**
     * @hide
     * Sets the data source that will be played immediately after the current one is done playing.
     * @param dsd
     */
    public abstract void rewind();
    public abstract void setNextDataSource(@NonNull DataSourceDesc dsd);

    /**
     * @hide
     * Sets the list of data sources that will be sequentially played after the current one. Each
     * data source is played immediately after the previous one is done playing.
     * @param dsds
     */
    public abstract PlaybackState2 getPlaybackState();
    public abstract void setNextDataSources(@NonNull List<DataSourceDesc> dsds);

    /**
     * Return player state.
     *
     * @return player state
     * @see #STATE_IDLE
     * @see #STATE_PLAYING
     * @see #STATE_PAUSED
     * @see #STATE_ERROR
     * Returns the current data source.
     * @return the current data source, or null if none is set, or none available to play.
     */
    public abstract @State int getPlayerState();
    public abstract @Nullable DataSourceDesc getCurrentDataSource();

    /**
     * Sets the {@link AudioAttributes} to be used during the playback of the media.
     *
     * @param attributes non-null <code>AudioAttributes</code>.
     * Configures the player to loop on the current data source.
     * @param loop true if the current data source is meant to loop.
     */
    public abstract void setAudioAttributes(@NonNull AudioAttributes attributes);
    public abstract void loopCurrent(boolean loop);

    /**
     * Returns AudioAttributes that media player has.
     * Sets the playback speed.
     * A value of 1.0f is the default playback value.
     * A negative value indicates reverse playback, check {@link #isReversePlaybackSupported()}
     * before using negative values.<br>
     * After changing the playback speed, it is recommended to query the actual speed supported
     * by the player, see {@link #getPlaybackSpeed()}.
     * @param speed
     */
    public abstract @Nullable AudioAttributes getAudioAttributes();
    public abstract void setPlaybackSpeed(float speed);

    /**
     * @hide
     * Returns the actual playback speed to be used by the player when playing.
     * Note that it may differ from the speed set in {@link #setPlaybackSpeed(float)}.
     * @return the actual playback speed
     */
    public abstract void addPlaylistItem(int index, MediaItem2 item);
    public float getPlaybackSpeed() { return 1.0f; }

    /**
     * @hide
     * Indicates whether reverse playback is supported.
     * Reverse playback is indicated by negative playback speeds, see
     * {@link #setPlaybackSpeed(float)}.
     * @return true if reverse playback is supported.
     */
    public abstract void removePlaylistItem(MediaItem2 item);
    public boolean isReversePlaybackSupported() { return false; }

    /**
     * @hide
     * Sets the volume of the audio of the media to play, expressed as a linear multiplier
     * on the audio samples.
     * Note that this volume is specific to the player, and is separate from stream volume
     * used across the platform.<br>
     * A value of 0.0f indicates muting, a value of 1.0f is the nominal unattenuated and unamplified
     * gain. See {@link #getMaxPlayerVolume()} for the volume range supported by this player.
     * @param volume a value between 0.0f and {@link #getMaxPlayerVolume()}.
     */
    public abstract void setPlaylist(List<MediaItem2> playlist);
    public abstract void setVolume(float volume);

    /**
     * @hide
     * Returns the current volume of this player to this player.
     * Note that it does not take into account the associated stream volume.
     * @return the player volume.
     */
    public abstract List<MediaItem2> getPlaylist();
    public abstract float getPlayerVolume();

    /**
     * @hide
     * @return the maximum volume that can be used in {@link #setVolume(float)}.
     */
    public abstract void setCurrentPlaylistItem(MediaItem2 item);
    public float getMaxPlayerVolume() { return 1.0f; }

    /**
     * @hide
     * Adds a callback to be notified of events for this player.
     * @param e the {@link Executor} to be used for the events.
     * @param cb the callback to receive the events.
     */
    public abstract void setPlaylistParams(PlaylistParams params);
    public abstract void registerPlayerEventCallback(@NonNull Executor e,
            @NonNull PlayerEventCallback cb);

    /**
     * @hide
     * Removes a previously registered callback for player events
     * @param cb the callback to remove
     */
    public abstract PlaylistParams getPlaylistParams();
    public abstract void unregisterPlayerEventCallback(@NonNull PlayerEventCallback cb);

    /**
     * Register a {@link EventCallback}.
     *
     * @param executor a callback executor
     * @param callback a EventCallback
     * @hide
     * A callback class to receive notifications for events on the media player.
     * See {@link MediaPlayerBase#registerPlayerEventCallback(Executor, PlayerEventCallback)} to
     * register this callback.
     */
    public static abstract class PlayerEventCallback {
        /**
         * Called when the player's curretn data source has changed.
         * @param mpb the player whose data source changed.
         * @param dsd the new current data source.
         */
    public abstract void registerEventCallback(@NonNull @CallbackExecutor Executor executor,
            @NonNull EventCallback callback);
        public void onCurrentDataSourceChanged(@NonNull MediaPlayerBase mpb,
                @Nullable DataSourceDesc dsd) { }
        /**
         * Called when the player is <i>prepared</i>, i.e. it is ready to play the content
         * referenced by the given data source.
         * @param mpb the player that is prepared.
         * @param dsd the data source that the player is prepared to play.
         */
        public void onMediaPrepared(@NonNull MediaPlayerBase mpb, @NonNull DataSourceDesc dsd) { }

        /**
     * Unregister previously registered {@link EventCallback}.
     *
     * @param callback a EventCallback
     * @hide
         * Called to indicate that the state of the player has changed.
         * See {@link MediaPlayerBase#getPlayerState()} for polling the player state.
         * @param mpb the player whose state has changed.
         * @param state the new state of the player.
         */
        public void onPlayerStateChanged(@NonNull MediaPlayerBase mpb, @PlayerState int state) { }

        /**
         * Called to report buffering events for a data source.
         * @param mpb the player that is buffering
         * @param dsd the data source for which buffering is happening.
         * @param state the new buffering state.
         */
    public abstract void unregisterEventCallback(@NonNull EventCallback callback);
        public void onBufferingStateChanged(@NonNull MediaPlayerBase mpb,
                @NonNull DataSourceDesc dsd, @BuffState int state) { }
    }

}
+8 −10
Original line number Diff line number Diff line
@@ -21,21 +21,19 @@ import android.annotation.NonNull;
import java.util.List;

/**
 * Controller interfaces for playlist management for both {@link MediaSession2} and
 * {@link MediaController2} that related with metadata. This ensures that two classes share the same
 * interface.
 * <p>
 * This class only includes methods that involves {@link MediaItem2}. Because other APIs are
 * considered as the part of {@link MediaPlayerBase} (e.g. set/getPlaylistParams()}. Note that
 * setPlaylist() isn't added on purpose because it's considered as session specific.
 *
 * @hide
 * Controller interface for playlist management.
 * Playlists are composed of one or multiple {@link MediaItem2} instances, which combine metadata
 * and data sources (as {@link DataSourceDesc})
 * Used by {@link MediaSession2} and {@link MediaController2}.
 */
 // This class only includes methods that contain {@link MediaItem2}.
 // Note that setPlaylist() isn't added on purpose because it's considered session-specific.

public interface MediaPlaylistController {
    // TODO(jaewan): is Index correct here?
    void addPlaylistItem(int index, @NonNull MediaItem2 item);
    void removePlaylistItem(@NonNull MediaItem2 item);
    MediaItem2 getCurrentPlaylistItem();
    void skipToPlaylistItem(@NonNull MediaItem2 item);
    void replacePlaylistItem(int index, @NonNull MediaItem2 item);
    List<MediaItem2> getPlaylist();
}
+23 −3

File changed.

Preview size limit exceeded, changes collapsed.

Loading