diff --git a/RELEASENOTES.md b/RELEASENOTES.md index b60dbc804f..b19e62a5e3 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -111,8 +111,10 @@ * Cronet extension: * Add `CronetDataSource.Factory.setRequestPriority` to allow setting the priority of requests made by `CronetDataSource` instances. -* Leanback: +* Leanback extension: * Deprecate `setControlDispatcher` in `LeanbackPlayerAdapter`. +* Media2 extension: + * Deprecate `setControlDispatcher` in `SessionPlayerConnector`. ### 2.14.2 (2021-07-20) diff --git a/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java b/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java index e8201e80dc..d8e29cc79f 100644 --- a/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java +++ b/extensions/media2/src/androidTest/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnectorTest.java @@ -44,6 +44,7 @@ import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.ext.media2.test.R; @@ -183,6 +184,45 @@ public class SessionPlayerConnectorTest { } } + @Test + @LargeTest + public void play_withForwardingPlayer_isSkipped() throws Exception { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + + Player forwardingPlayer = null; + SessionPlayerConnector playerConnector = null; + try { + Player simpleExoPlayer = + new SimpleExoPlayer.Builder(context).setLooper(Looper.myLooper()).build(); + forwardingPlayer = + new ForwardingPlayer(simpleExoPlayer) { + @Override + public boolean isCommandAvailable(int command) { + if (command == COMMAND_PLAY_PAUSE) { + return false; + } + return super.isCommandAvailable(command); + } + + @Override + public Commands getAvailableCommands() { + return super.getAvailableCommands().buildUpon().remove(COMMAND_PLAY_PAUSE).build(); + } + }; + playerConnector = new SessionPlayerConnector(forwardingPlayer); + assertPlayerResult(playerConnector.play(), RESULT_INFO_SKIPPED); + } finally { + if (playerConnector != null) { + playerConnector.close(); + } + if (forwardingPlayer != null) { + forwardingPlayer.release(); + } + } + } + @Test @LargeTest public void setMediaItem_withAudioResource_notifiesOnPlaybackCompleted() throws Exception { diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java index a5cbcdb374..1b6b5683d4 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/PlayerWrapper.java @@ -15,6 +15,14 @@ */ package com.google.android.exoplayer2.ext.media2; +import static com.google.android.exoplayer2.Player.COMMAND_GET_AUDIO_ATTRIBUTES; +import static com.google.android.exoplayer2.Player.COMMAND_PLAY_PAUSE; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_IN_CURRENT_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_NEXT; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_PREVIOUS; +import static com.google.android.exoplayer2.Player.COMMAND_SEEK_TO_WINDOW; +import static com.google.android.exoplayer2.Player.COMMAND_SET_REPEAT_MODE; +import static com.google.android.exoplayer2.Player.COMMAND_SET_SHUFFLE_MODE; import static com.google.android.exoplayer2.util.Util.postOrRun; import android.os.Handler; @@ -27,6 +35,7 @@ import androidx.media2.common.SessionPlayer; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.ControlDispatcher; import com.google.android.exoplayer2.DefaultControlDispatcher; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.MediaItem; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; @@ -154,6 +163,12 @@ import java.util.List; } } + /** + * @deprecated Use a {@link ForwardingPlayer} and pass it to the constructor instead. You can also + * customize some operations when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). + */ + @Deprecated public void setControlDispatcher(ControlDispatcher controlDispatcher) { this.controlDispatcher = controlDispatcher; } @@ -231,11 +246,13 @@ import java.util.List; } public boolean skipToPreviousPlaylistItem() { - return controlDispatcher.dispatchPrevious(player); + return player.isCommandAvailable(COMMAND_SEEK_TO_PREVIOUS) + && controlDispatcher.dispatchPrevious(player); } public boolean skipToNextPlaylistItem() { - return controlDispatcher.dispatchNext(player); + return player.isCommandAvailable(COMMAND_SEEK_TO_NEXT) + && controlDispatcher.dispatchNext(player); } public boolean skipToPlaylistItem(@IntRange(from = 0) int index) { @@ -247,7 +264,8 @@ import java.util.List; Assertions.checkState(0 <= index && index < timeline.getWindowCount()); int windowIndex = player.getCurrentWindowIndex(); if (windowIndex != index) { - return controlDispatcher.dispatchSeekTo(player, index, C.TIME_UNSET); + return player.isCommandAvailable(COMMAND_SEEK_TO_WINDOW) + && controlDispatcher.dispatchSeekTo(player, index, C.TIME_UNSET); } return false; } @@ -258,13 +276,15 @@ import java.util.List; } public boolean setRepeatMode(int repeatMode) { - return controlDispatcher.dispatchSetRepeatMode( - player, Utils.getExoPlayerRepeatMode(repeatMode)); + return player.isCommandAvailable(COMMAND_SET_REPEAT_MODE) + && controlDispatcher.dispatchSetRepeatMode( + player, Utils.getExoPlayerRepeatMode(repeatMode)); } public boolean setShuffleMode(int shuffleMode) { - return controlDispatcher.dispatchSetShuffleModeEnabled( - player, Utils.getExoPlayerShuffleMode(shuffleMode)); + return player.isCommandAvailable(COMMAND_SET_SHUFFLE_MODE) + && controlDispatcher.dispatchSetShuffleModeEnabled( + player, Utils.getExoPlayerShuffleMode(shuffleMode)); } @Nullable @@ -314,8 +334,9 @@ import java.util.List; public boolean play() { if (player.getPlaybackState() == Player.STATE_ENDED) { boolean seekHandled = - controlDispatcher.dispatchSeekTo( - player, player.getCurrentWindowIndex(), /* positionMs= */ 0); + player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW) + && controlDispatcher.dispatchSeekTo( + player, player.getCurrentWindowIndex(), /* positionMs= */ 0); if (!seekHandled) { return false; } @@ -325,7 +346,8 @@ import java.util.List; if (playWhenReady && suppressReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE) { return false; } - return controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true); + return player.isCommandAvailable(COMMAND_PLAY_PAUSE) + && controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ true); } public boolean pause() { @@ -334,11 +356,13 @@ import java.util.List; if (!playWhenReady && suppressReason == Player.PLAYBACK_SUPPRESSION_REASON_NONE) { return false; } - return controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false); + return player.isCommandAvailable(COMMAND_PLAY_PAUSE) + && controlDispatcher.dispatchSetPlayWhenReady(player, /* playWhenReady= */ false); } public boolean seekTo(long position) { - return controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), position); + return player.isCommandAvailable(COMMAND_SEEK_IN_CURRENT_WINDOW) + && controlDispatcher.dispatchSeekTo(player, player.getCurrentWindowIndex(), position); } public long getCurrentPosition() { @@ -443,7 +467,7 @@ import java.util.List; public AudioAttributesCompat getAudioAttributes() { AudioAttributes audioAttributes = AudioAttributes.DEFAULT; - if (player.isCommandAvailable(Player.COMMAND_GET_AUDIO_ATTRIBUTES)) { + if (player.isCommandAvailable(COMMAND_GET_AUDIO_ATTRIBUTES)) { audioAttributes = player.getAudioAttributes(); } return Utils.getAudioAttributesCompat(audioAttributes); diff --git a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java index 16ee3274e9..e2eb6d1134 100644 --- a/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java +++ b/extensions/media2/src/main/java/com/google/android/exoplayer2/ext/media2/SessionPlayerConnector.java @@ -30,8 +30,8 @@ import androidx.media2.common.MediaItem; import androidx.media2.common.MediaMetadata; import androidx.media2.common.SessionPlayer; import com.google.android.exoplayer2.ControlDispatcher; -import com.google.android.exoplayer2.DefaultControlDispatcher; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; +import com.google.android.exoplayer2.ForwardingPlayer; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.util.Assertions; import com.google.android.exoplayer2.util.Log; @@ -87,7 +87,7 @@ public final class SessionPlayerConnector extends SessionPlayer { /** * Creates an instance using {@link DefaultMediaItemConverter} to convert between ExoPlayer and - * media2 MediaItems and {@link DefaultControlDispatcher} to dispatch player commands. + * media2 MediaItems. * * @param player The player to wrap. */ @@ -96,7 +96,7 @@ public final class SessionPlayerConnector extends SessionPlayer { } /** - * Creates an instance using the provided {@link ControlDispatcher} to dispatch player commands. + * Creates an instance. * * @param player The player to wrap. * @param mediaItemConverter The {@link MediaItemConverter}. @@ -114,10 +114,11 @@ public final class SessionPlayerConnector extends SessionPlayer { } /** - * Sets the {@link ControlDispatcher}. - * - * @param controlDispatcher The {@link ControlDispatcher}. + * @deprecated Use a {@link ForwardingPlayer} and pass it to the constructor instead. You can also + * customize some operations when configuring the player (for example by using {@code + * SimpleExoPlayer.Builder#setSeekBackIncrementMs(long)}). */ + @Deprecated public void setControlDispatcher(ControlDispatcher controlDispatcher) { player.setControlDispatcher(controlDispatcher); }