diff --git a/api/current.txt b/api/current.txt index ba76c70a079db..53d1d6f620fc2 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24852,6 +24852,7 @@ package android.media { public class MediaSession2 implements java.lang.AutoCloseable android.media.MediaPlaylistController { method public void addPlaylistItem(int, android.media.MediaItem2); + method public void clearOnDataSourceMissingHelper(); method public void close(); method public void fastForward(); method public java.util.List getConnectedControllers(); @@ -24879,6 +24880,7 @@ package android.media { method public void setAllowedCommands(android.media.MediaSession2.ControllerInfo, android.media.MediaSession2.CommandGroup); method public void setAudioFocusRequest(android.media.AudioFocusRequest); method public void setCustomLayout(android.media.MediaSession2.ControllerInfo, java.util.List); + method public void setOnDataSourceMissingHelper(android.media.MediaSession2.OnDataSourceMissingHelper); method public void setPlaybackSpeed(float); method public void setPlaylist(java.util.List, android.media.MediaMetadata2); method public void setRepeatMode(int); @@ -24988,6 +24990,10 @@ package android.media { method public boolean isTrusted(); } + public static abstract interface MediaSession2.OnDataSourceMissingHelper { + method public abstract android.media.DataSourceDesc onDataSourceMissing(android.media.MediaSession2, android.media.MediaItem2); + } + public static abstract class MediaSession2.SessionCallback { ctor public MediaSession2.SessionCallback(android.content.Context); method public void onBufferingStateChanged(android.media.MediaSession2, android.media.MediaPlayerBase, android.media.MediaItem2, int); diff --git a/media/java/android/media/MediaItem2.java b/media/java/android/media/MediaItem2.java index f6edd0c0b25d9..2db1392a9d83b 100644 --- a/media/java/android/media/MediaItem2.java +++ b/media/java/android/media/MediaItem2.java @@ -139,6 +139,13 @@ public class MediaItem2 { return mProvider.getDataSourceDesc_impl(); } + @Override + public boolean equals(Object obj) { + // TODO(jaewan): Override this. MediaItem2 may have auto-generated srcId when the DSD isn't + // set, and it should be compared for the equals. + return super.equals(obj); + } + /** * Build {@link MediaItem2} */ @@ -189,12 +196,12 @@ public class MediaItem2 { } /** - * Set the data source descriptor for this instance. Should not be {@code null}. + * Set the data source descriptor for this instance. {@code null} for unset. * * @param dataSourceDesc data source descriptor * @return this instance for chaining */ - public Builder setDataSourceDesc(@NonNull DataSourceDesc dataSourceDesc) { + public Builder setDataSourceDesc(@Nullable DataSourceDesc dataSourceDesc) { return mProvider.setDataSourceDesc_impl(dataSourceDesc); } diff --git a/media/java/android/media/MediaSession2.java b/media/java/android/media/MediaSession2.java index ddb51c3e697d2..b75785abef76a 100644 --- a/media/java/android/media/MediaSession2.java +++ b/media/java/android/media/MediaSession2.java @@ -407,6 +407,29 @@ public class MediaSession2 implements AutoCloseable, MediaPlaylistController { */ public static final int ERROR_CODE_SETUP_REQUIRED = 12; + /** + * Interface definition of a callback to be invoked when a {@link MediaItem2} in the playlist + * didn't have a {@link DataSourceDesc} but it's needed now for preparing or playing it. + * + * #see #setOnDataSourceMissingHelper + */ + public interface OnDataSourceMissingHelper { + /** + * Called when a {@link MediaItem2} in the playlist didn't have a {@link DataSourceDesc} + * but it's needed now for preparing or playing it. + *

+ * Returned data source descriptor will be sent to the player directly to prepare or play + * the contents. + * + * @param session the session for this event + * @param item media item from the controller + * @return a data source descriptor if the media item. Can be {@code null} if the content + * isn't available. + */ + @Nullable DataSourceDesc onDataSourceMissing(@NonNull MediaSession2 session, + @NonNull MediaItem2 item); + } + /** * Define a command that a {@link MediaController2} can send to a {@link MediaSession2}. *

@@ -1357,7 +1380,7 @@ public class MediaSession2 implements AutoCloseable, MediaPlaylistController { * This API can be called in the {@link SessionCallback#onConnect(MediaSession2, ControllerInfo)}. * * @param controller controller to specify layout. - * @param layout oredered list of layout. + * @param layout ordered list of layout. */ public void setCustomLayout(@NonNull ControllerInfo controller, @NonNull List layout) { @@ -1564,6 +1587,46 @@ public class MediaSession2 implements AutoCloseable, MediaPlaylistController { // TODO(jaewan): implement this (b/74093080) } + /** + * Sets the data source missing helper. Helper will be used to provide default implementation of + * {@link MediaPlaylistController} when it isn't set by developer. + *

+ * Default implementation of the {@link MediaPlaylistController} will call helper when a + * {@link MediaItem2} in the playlist doesn't have a {@link DataSourceDesc}. This may happen + * when + *

    + *
  • {@link MediaItem2} specified by {@link #setPlaylist(List, MediaMetadata2)} doesn't + * have {@link DataSourceDesc}
  • + *
  • {@link MediaController2#addPlaylistItem(int, MediaItem2)} is called and accepted + * by {@link SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command)}. + * In that case, an item would be added automatically without the data source.
  • + *
+ *

+ * If it's not set, playback wouldn't happen for the item without data source descriptor. + *

+ * The helper will be run on the executor that you've specified by the + * {@link Builder#setSessionCallback(Executor, SessionCallback)}. + * + * @param helper a data source misisng helper. + * @throws IllegalStateException when the helper is set when the playlist controller is set + * @see #setPlaylist(List, MediaMetadata2) + * @see SessionCallback#onCommandRequest(MediaSession2, ControllerInfo, Command) + * @see #COMMAND_CODE_PLAYLIST_ADD_ITEM + * @see #COMMAND_CODE_PLAYLIST_REPLACE_ITEM + */ + public void setOnDataSourceMissingHelper(@NonNull OnDataSourceMissingHelper helper) { + // TODO(jaewan): Implement (b/74090741) + } + + /** + * Clears the data source missing helper. + * + * @see #setOnDataSourceMissingHelper(OnDataSourceMissingHelper) + */ + public void clearOnDataSourceMissingHelper() { + // TODO(jaewan): Implement (b/74090741) + } + /** * Register {@link MediaPlaylistController.PlaylistEventCallback} to listen changes in the * underlying {@link MediaPlaylistController}, regardless of the change in the controller. @@ -1615,6 +1678,16 @@ public class MediaSession2 implements AutoCloseable, MediaPlaylistController { mProvider.setPlaylist_impl(playlist); } + /** + * Set a list of {@link MediaItem2} as the current play list. + *

+ * You may specify a {@link MediaItem2} without {@link DataSourceDesc}. However, in that case, + * you should set {@link OnDataSourceMissingHelper} for player to prepare. + * + * @param list A list of {@link MediaItem2} objects to set as a play list. + * @throws IllegalArgumentException if given {@param playlist} is null. + * @see #setOnDataSourceMissingHelper + */ @Override public void setPlaylist(@NonNull List list, @Nullable MediaMetadata2 metadata) { // TODO(jaewan): Implement (b/74174649)