Commit 2f1c0a5d by sungsoo Committed by Ian Baker

Allow to remove all playlist items

PiperOrigin-RevId: 343437513
parent d67b7034
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
* Media2 extention: * Media2 extention:
* Notify onBufferingEnded when the state of origin player becomes * Notify onBufferingEnded when the state of origin player becomes
STATE_IDLE or STATE_ENDED. STATE_IDLE or STATE_ENDED.
* Allow to remove all playlist items that makes the player reset.
### 2.12.1 (2020-10-23) ### ### 2.12.1 (2020-10-23) ###
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
package com.google.android.exoplayer2.ext.media2; package com.google.android.exoplayer2.ext.media2;
import static androidx.media2.common.SessionPlayer.PLAYER_STATE_IDLE;
import static androidx.media2.common.SessionPlayer.PLAYER_STATE_PAUSED; import static androidx.media2.common.SessionPlayer.PLAYER_STATE_PAUSED;
import static androidx.media2.common.SessionPlayer.PLAYER_STATE_PLAYING; import static androidx.media2.common.SessionPlayer.PLAYER_STATE_PLAYING;
import static androidx.media2.common.SessionPlayer.PlayerResult.RESULT_INFO_SKIPPED; import static androidx.media2.common.SessionPlayer.PlayerResult.RESULT_INFO_SKIPPED;
...@@ -60,6 +61,7 @@ import java.util.List; ...@@ -60,6 +61,7 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.junit.Before; import org.junit.Before;
...@@ -762,13 +764,11 @@ public class SessionPlayerConnectorTest { ...@@ -762,13 +764,11 @@ public class SessionPlayerConnectorTest {
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
public void setPlaylist_setsPlaylistAndCurrentMediaItem() throws Exception { public void setPlaylist_setsPlaylistAndCurrentMediaItem() throws Exception {
List<MediaItem> playlist = TestUtils.createPlaylist(10); List<MediaItem> playlist = TestUtils.createPlaylist(10);
CountDownLatch onCurrentMediaItemChangedLatch = new CountDownLatch(1); PlayerCallbackForPlaylist callback = new PlayerCallbackForPlaylist(playlist, 1);
sessionPlayerConnector.registerPlayerCallback( sessionPlayerConnector.registerPlayerCallback(executor, callback);
executor, new PlayerCallbackForPlaylist(playlist, onCurrentMediaItemChangedLatch));
assertPlayerResultSuccess(sessionPlayerConnector.setPlaylist(playlist, null)); assertPlayerResultSuccess(sessionPlayerConnector.setPlaylist(playlist, null));
assertThat(onCurrentMediaItemChangedLatch.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)) assertThat(callback.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
.isTrue();
assertThat(sessionPlayerConnector.getPlaylist()).isEqualTo(playlist); assertThat(sessionPlayerConnector.getPlaylist()).isEqualTo(playlist);
assertThat(sessionPlayerConnector.getCurrentMediaItem()).isEqualTo(playlist.get(0)); assertThat(sessionPlayerConnector.getCurrentMediaItem()).isEqualTo(playlist.get(0));
...@@ -777,6 +777,32 @@ public class SessionPlayerConnectorTest { ...@@ -777,6 +777,32 @@ public class SessionPlayerConnectorTest {
@Test @Test
@LargeTest @LargeTest
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
public void setPlaylistAndRemoveAllPlaylistItem_playerStateBecomesIdle() throws Exception {
List<MediaItem> playlist = new ArrayList<>();
playlist.add(TestUtils.createMediaItem(R.raw.video_1));
PlayerCallbackForPlaylist callback =
new PlayerCallbackForPlaylist(playlist, 2) {
@Override
public void onPlayerStateChanged(@NonNull SessionPlayer player, int playerState) {
countDown();
}
};
sessionPlayerConnector.registerPlayerCallback(executor, callback);
assertPlayerResultSuccess(sessionPlayerConnector.setPlaylist(playlist, null));
assertPlayerResultSuccess(sessionPlayerConnector.prepare());
assertThat(callback.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
assertThat(sessionPlayerConnector.getPlayerState()).isEqualTo(PLAYER_STATE_PAUSED);
callback.resetLatch(1);
assertPlayerResultSuccess(sessionPlayerConnector.removePlaylistItem(0));
assertThat(callback.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
assertThat(sessionPlayerConnector.getPlayerState()).isEqualTo(PLAYER_STATE_IDLE);
}
@Test
@LargeTest
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
public void setPlaylist_calledOnlyOnce_notifiesPlaylistChangeOnlyOnce() throws Exception { public void setPlaylist_calledOnlyOnce_notifiesPlaylistChangeOnlyOnce() throws Exception {
List<MediaItem> playlist = TestUtils.createPlaylist(10); List<MediaItem> playlist = TestUtils.createPlaylist(10);
CountDownLatch onPlaylistChangedLatch = new CountDownLatch(2); CountDownLatch onPlaylistChangedLatch = new CountDownLatch(2);
...@@ -958,14 +984,12 @@ public class SessionPlayerConnectorTest { ...@@ -958,14 +984,12 @@ public class SessionPlayerConnectorTest {
int listSize = 2; int listSize = 2;
List<MediaItem> playlist = TestUtils.createPlaylist(listSize); List<MediaItem> playlist = TestUtils.createPlaylist(listSize);
CountDownLatch onCurrentMediaItemChangedLatch = new CountDownLatch(1); PlayerCallbackForPlaylist callback = new PlayerCallbackForPlaylist(playlist, 1);
sessionPlayerConnector.registerPlayerCallback( sessionPlayerConnector.registerPlayerCallback(executor, callback);
executor, new PlayerCallbackForPlaylist(playlist, onCurrentMediaItemChangedLatch));
assertPlayerResultSuccess(sessionPlayerConnector.setPlaylist(playlist, null)); assertPlayerResultSuccess(sessionPlayerConnector.setPlaylist(playlist, null));
assertThat(sessionPlayerConnector.getCurrentMediaItemIndex()).isEqualTo(0); assertThat(sessionPlayerConnector.getCurrentMediaItemIndex()).isEqualTo(0);
assertThat(onCurrentMediaItemChangedLatch.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)) assertThat(callback.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
.isTrue();
} }
@Test @Test
...@@ -1193,16 +1217,15 @@ public class SessionPlayerConnectorTest { ...@@ -1193,16 +1217,15 @@ public class SessionPlayerConnectorTest {
int listSize = playlist.size(); int listSize = playlist.size();
// Any value more than list size + 1, to see repeat mode with the recorded video. // Any value more than list size + 1, to see repeat mode with the recorded video.
CountDownLatch onCurrentMediaItemChangedLatch = new CountDownLatch(listSize + 2);
CopyOnWriteArrayList<MediaItem> currentMediaItemChanges = new CopyOnWriteArrayList<>(); CopyOnWriteArrayList<MediaItem> currentMediaItemChanges = new CopyOnWriteArrayList<>();
PlayerCallbackForPlaylist callback = PlayerCallbackForPlaylist callback =
new PlayerCallbackForPlaylist(playlist, onCurrentMediaItemChangedLatch) { new PlayerCallbackForPlaylist(playlist, listSize + 2) {
@Override @Override
public void onCurrentMediaItemChanged( public void onCurrentMediaItemChanged(
@NonNull SessionPlayer player, @NonNull MediaItem item) { @NonNull SessionPlayer player, @NonNull MediaItem item) {
super.onCurrentMediaItemChanged(player, item); super.onCurrentMediaItemChanged(player, item);
currentMediaItemChanges.add(item); currentMediaItemChanges.add(item);
onCurrentMediaItemChangedLatch.countDown(); countDown();
} }
@Override @Override
...@@ -1223,7 +1246,7 @@ public class SessionPlayerConnectorTest { ...@@ -1223,7 +1246,7 @@ public class SessionPlayerConnectorTest {
assertWithMessage( assertWithMessage(
"Current media item didn't change as expected. Actual changes were %s", "Current media item didn't change as expected. Actual changes were %s",
currentMediaItemChanges) currentMediaItemChanges)
.that(onCurrentMediaItemChangedLatch.await(PLAYBACK_COMPLETED_WAIT_TIME_MS, MILLISECONDS)) .that(callback.await(PLAYBACK_COMPLETED_WAIT_TIME_MS, MILLISECONDS))
.isTrue(); .isTrue();
int expectedMediaItemIndex = 0; int expectedMediaItemIndex = 0;
...@@ -1285,9 +1308,9 @@ public class SessionPlayerConnectorTest { ...@@ -1285,9 +1308,9 @@ public class SessionPlayerConnectorTest {
private List<MediaItem> playlist; private List<MediaItem> playlist;
private CountDownLatch onCurrentMediaItemChangedLatch; private CountDownLatch onCurrentMediaItemChangedLatch;
PlayerCallbackForPlaylist(List<MediaItem> playlist, CountDownLatch latch) { PlayerCallbackForPlaylist(List<MediaItem> playlist, int count) {
this.playlist = playlist; this.playlist = playlist;
onCurrentMediaItemChangedLatch = latch; onCurrentMediaItemChangedLatch = new CountDownLatch(count);
} }
@Override @Override
...@@ -1296,5 +1319,17 @@ public class SessionPlayerConnectorTest { ...@@ -1296,5 +1319,17 @@ public class SessionPlayerConnectorTest {
assertThat(sessionPlayerConnector.getCurrentMediaItemIndex()).isEqualTo(currentIndex); assertThat(sessionPlayerConnector.getCurrentMediaItemIndex()).isEqualTo(currentIndex);
onCurrentMediaItemChangedLatch.countDown(); onCurrentMediaItemChangedLatch.countDown();
} }
public void resetLatch(int count) {
onCurrentMediaItemChangedLatch = new CountDownLatch(count);
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
return onCurrentMediaItemChangedLatch.await(timeout, unit);
}
public void countDown() {
onCurrentMediaItemChangedLatch.countDown();
}
} }
} }
...@@ -207,6 +207,9 @@ import java.util.List; ...@@ -207,6 +207,9 @@ import java.util.List;
} }
public boolean removePlaylistItem(@IntRange(from = 0) int index) { public boolean removePlaylistItem(@IntRange(from = 0) int index) {
if (player.getMediaItemCount() <= index) {
return false;
}
player.removeMediaItem(index); player.removeMediaItem(index);
return true; return true;
} }
...@@ -374,7 +377,9 @@ import java.util.List; ...@@ -374,7 +377,9 @@ import java.util.List;
case Player.STATE_IDLE: case Player.STATE_IDLE:
return SessionPlayer.PLAYER_STATE_IDLE; return SessionPlayer.PLAYER_STATE_IDLE;
case Player.STATE_ENDED: case Player.STATE_ENDED:
return SessionPlayer.PLAYER_STATE_PAUSED; return player.getCurrentMediaItem() == null
? SessionPlayer.PLAYER_STATE_IDLE
: SessionPlayer.PLAYER_STATE_PAUSED;
case Player.STATE_BUFFERING: case Player.STATE_BUFFERING:
case Player.STATE_READY: case Player.STATE_READY:
return playWhenReady return playWhenReady
...@@ -435,7 +440,9 @@ import java.util.List; ...@@ -435,7 +440,9 @@ import java.util.List;
postOrRun(handler, pollBufferRunnable); postOrRun(handler, pollBufferRunnable);
break; break;
case Player.STATE_ENDED: case Player.STATE_ENDED:
listener.onPlaybackEnded(); if (player.getCurrentMediaItem() != null) {
listener.onPlaybackEnded();
}
player.setPlayWhenReady(false); player.setPlayWhenReady(false);
updateBufferingState(/* isBuffering= */ false); updateBufferingState(/* isBuffering= */ false);
break; break;
......
...@@ -559,12 +559,16 @@ public final class SessionPlayerConnector extends SessionPlayer { ...@@ -559,12 +559,16 @@ public final class SessionPlayerConnector extends SessionPlayer {
} }
} }
// TODO: Remove this suppress warnings and call onCurrentMediaItemChanged with a null item
// once AndroidX media2 1.2.0 is released
@SuppressWarnings("nullness:argument.type.incompatible")
private void handlePlaylistChangedOnHandler() { private void handlePlaylistChangedOnHandler() {
List<MediaItem> currentPlaylist = player.getPlaylist(); List<MediaItem> currentPlaylist = player.getPlaylist();
MediaMetadata playlistMetadata = player.getPlaylistMetadata(); MediaMetadata playlistMetadata = player.getPlaylistMetadata();
MediaItem currentMediaItem = player.getCurrentMediaItem(); MediaItem currentMediaItem = player.getCurrentMediaItem();
boolean notifyCurrentMediaItem = !ObjectsCompat.equals(this.currentMediaItem, currentMediaItem); boolean notifyCurrentMediaItem =
!ObjectsCompat.equals(this.currentMediaItem, currentMediaItem) && currentMediaItem != null;
this.currentMediaItem = currentMediaItem; this.currentMediaItem = currentMediaItem;
long currentPosition = getCurrentPosition(); long currentPosition = getCurrentPosition();
...@@ -573,9 +577,6 @@ public final class SessionPlayerConnector extends SessionPlayer { ...@@ -573,9 +577,6 @@ public final class SessionPlayerConnector extends SessionPlayer {
callback.onPlaylistChanged( callback.onPlaylistChanged(
SessionPlayerConnector.this, currentPlaylist, playlistMetadata); SessionPlayerConnector.this, currentPlaylist, playlistMetadata);
if (notifyCurrentMediaItem) { if (notifyCurrentMediaItem) {
Assertions.checkNotNull(
currentMediaItem, "PlaylistManager#currentMediaItem() cannot be changed to null");
callback.onCurrentMediaItemChanged(SessionPlayerConnector.this, currentMediaItem); callback.onCurrentMediaItemChanged(SessionPlayerConnector.this, currentMediaItem);
// Workaround for MediaSession's issue that current media item change isn't propagated // Workaround for MediaSession's issue that current media item change isn't propagated
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment