Make ExoPlayer as the trusted source of playlist

Playlist can now be obtained directly from Timeline windows
in any state. So make ExoPlayer as the trusted source of
playlist, instead of SessionPlayerConnector.

PlayerWrapper still need to keep the list of media items.
It's used to detect whether the Timeline change is caused by
changes in media items or not, and only notify
SessionPlayer.PlayerCallback#onPlaylistChanged() only when
the playlist is really changed.

PiperOrigin-RevId: 327231820
This commit is contained in:
jaewan 2020-08-18 16:25:32 +01:00 committed by Oliver Woodman
parent 79a846eb5e
commit b39721f4b5
5 changed files with 188 additions and 124 deletions

View File

@ -33,6 +33,7 @@ import android.os.Build.VERSION_CODES;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.ObjectsCompat;
import androidx.media.AudioAttributesCompat;
import androidx.media2.common.MediaItem;
import androidx.media2.common.MediaMetadata;
@ -61,6 +62,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -795,6 +797,73 @@ public class SessionPlayerConnectorTest {
assertThat(onPlaylistChangedLatch.getCount()).isEqualTo(1);
}
@Test
@LargeTest
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
public void setPlaylist_byUnderlyingPlayerBeforePrepare_notifiesOnPlaylistChanged()
throws Exception {
List<MediaItem> playlistToSessionPlayer = TestUtils.createPlaylist(2);
List<MediaItem> playlistToExoPlayer = TestUtils.createPlaylist(4);
DefaultMediaItemConverter converter = new DefaultMediaItemConverter();
List<com.google.android.exoplayer2.MediaItem> exoMediaItems = new ArrayList<>();
for (MediaItem mediaItem : playlistToExoPlayer) {
exoMediaItems.add(converter.convertToExoPlayerMediaItem(mediaItem));
}
CountDownLatch onPlaylistChangedLatch = new CountDownLatch(1);
sessionPlayerConnector.registerPlayerCallback(
executor,
new SessionPlayer.PlayerCallback() {
@Override
public void onPlaylistChanged(
@NonNull SessionPlayer player,
@Nullable List<MediaItem> list,
@Nullable MediaMetadata metadata) {
if (ObjectsCompat.equals(list, playlistToExoPlayer)) {
onPlaylistChangedLatch.countDown();
}
}
});
sessionPlayerConnector.setPlaylist(playlistToSessionPlayer, /* metadata= */ null);
InstrumentationRegistry.getInstrumentation()
.runOnMainSync(() -> playerTestRule.getSimpleExoPlayer().setMediaItems(exoMediaItems));
assertThat(onPlaylistChangedLatch.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
}
@Test
@LargeTest
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
public void setPlaylist_byUnderlyingPlayerAfterPrepare_notifiesOnPlaylistChanged()
throws Exception {
List<MediaItem> playlistToSessionPlayer = TestUtils.createPlaylist(2);
List<MediaItem> playlistToExoPlayer = TestUtils.createPlaylist(4);
DefaultMediaItemConverter converter = new DefaultMediaItemConverter();
List<com.google.android.exoplayer2.MediaItem> exoMediaItems = new ArrayList<>();
for (MediaItem mediaItem : playlistToExoPlayer) {
exoMediaItems.add(converter.convertToExoPlayerMediaItem(mediaItem));
}
CountDownLatch onPlaylistChangedLatch = new CountDownLatch(1);
sessionPlayerConnector.registerPlayerCallback(
executor,
new SessionPlayer.PlayerCallback() {
@Override
public void onPlaylistChanged(
@NonNull SessionPlayer player,
@Nullable List<MediaItem> list,
@Nullable MediaMetadata metadata) {
if (ObjectsCompat.equals(list, playlistToExoPlayer)) {
onPlaylistChangedLatch.countDown();
}
}
});
sessionPlayerConnector.prepare();
sessionPlayerConnector.setPlaylist(playlistToSessionPlayer, /* metadata= */ null);
InstrumentationRegistry.getInstrumentation()
.runOnMainSync(() -> playerTestRule.getSimpleExoPlayer().setMediaItems(exoMediaItems));
assertThat(onPlaylistChangedLatch.await(PLAYLIST_CHANGE_WAIT_TIME_MS, MILLISECONDS)).isTrue();
}
@Test
@LargeTest
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT)
@ -862,7 +931,7 @@ public class SessionPlayerConnectorTest {
CountDownLatch onPlaylistChangedLatch = new CountDownLatch(2);
int replaceIndex = 2;
MediaItem newMediaItem = TestUtils.createMediaItem();
MediaItem newMediaItem = TestUtils.createMediaItem(R.raw.video_big_buck_bunny);
playlist.set(replaceIndex, newMediaItem);
sessionPlayerConnector.registerPlayerCallback(
executor,
@ -1185,6 +1254,32 @@ public class SessionPlayerConnectorTest {
assertThat(sessionPlayerConnector.getPlayerState()).isEqualTo(PLAYER_STATE_PLAYING);
}
@Test
@LargeTest
public void getPlaylist_returnsPlaylistInUnderlyingPlayer() {
List<MediaItem> playlistToExoPlayer = TestUtils.createPlaylist(4);
DefaultMediaItemConverter converter = new DefaultMediaItemConverter();
List<com.google.android.exoplayer2.MediaItem> exoMediaItems = new ArrayList<>();
for (MediaItem mediaItem : playlistToExoPlayer) {
exoMediaItems.add(converter.convertToExoPlayerMediaItem(mediaItem));
}
AtomicReference<List<MediaItem>> playlistFromSessionPlayer = new AtomicReference<>();
InstrumentationRegistry.getInstrumentation()
.runOnMainSync(
() -> {
SimpleExoPlayer simpleExoPlayer = playerTestRule.getSimpleExoPlayer();
simpleExoPlayer.setMediaItems(exoMediaItems);
try (SessionPlayerConnector sessionPlayer =
new SessionPlayerConnector(simpleExoPlayer, converter)) {
List<MediaItem> playlist = sessionPlayer.getPlaylist();
playlistFromSessionPlayer.set(playlist);
}
});
assertThat(playlistFromSessionPlayer.get()).isEqualTo(playlistToExoPlayer);
}
private class PlayerCallbackForPlaylist extends SessionPlayer.PlayerCallback {
private List<MediaItem> playlist;
private CountDownLatch onCurrentMediaItemChangedLatch;

View File

@ -37,10 +37,10 @@ public final class DefaultMediaItemConverter implements MediaItemConverter {
throw new IllegalStateException("CallbackMediaItem isn't supported");
}
MediaItem.Builder exoplayerMediaItemBuilder = new MediaItem.Builder();
MediaItem.Builder exoPlayerMediaItemBuilder = new MediaItem.Builder();
// Set mediaItem as tag for creating MediaSource via MediaSourceFactory methods.
exoplayerMediaItemBuilder.setTag(androidXMediaItem);
exoPlayerMediaItemBuilder.setTag(androidXMediaItem);
// Media ID or URI must be present. Get it from androidx.MediaItem if possible.
@Nullable Uri uri = null;
@ -61,31 +61,31 @@ public final class DefaultMediaItemConverter implements MediaItemConverter {
// Generate a Uri to make it non-null. If not, tag will be ignored.
uri = Uri.parse("exoplayer://" + androidXMediaItem.hashCode());
}
exoplayerMediaItemBuilder.setUri(uri);
exoplayerMediaItemBuilder.setMediaId(mediaId);
exoPlayerMediaItemBuilder.setUri(uri);
exoPlayerMediaItemBuilder.setMediaId(mediaId);
if (androidXMediaItem.getStartPosition() != androidx.media2.common.MediaItem.POSITION_UNKNOWN) {
exoplayerMediaItemBuilder.setClipStartPositionMs(androidXMediaItem.getStartPosition());
exoplayerMediaItemBuilder.setClipRelativeToDefaultPosition(true);
exoPlayerMediaItemBuilder.setClipStartPositionMs(androidXMediaItem.getStartPosition());
exoPlayerMediaItemBuilder.setClipRelativeToDefaultPosition(true);
}
if (androidXMediaItem.getEndPosition() != androidx.media2.common.MediaItem.POSITION_UNKNOWN) {
exoplayerMediaItemBuilder.setClipEndPositionMs(androidXMediaItem.getEndPosition());
exoplayerMediaItemBuilder.setClipRelativeToDefaultPosition(true);
exoPlayerMediaItemBuilder.setClipEndPositionMs(androidXMediaItem.getEndPosition());
exoPlayerMediaItemBuilder.setClipRelativeToDefaultPosition(true);
}
return exoplayerMediaItemBuilder.build();
return exoPlayerMediaItemBuilder.build();
}
@Override
public androidx.media2.common.MediaItem convertToAndroidXMediaItem(MediaItem exoplayerMediaItem) {
Assertions.checkNotNull(exoplayerMediaItem);
public androidx.media2.common.MediaItem convertToAndroidXMediaItem(MediaItem exoPlayerMediaItem) {
Assertions.checkNotNull(exoPlayerMediaItem);
MediaItem.PlaybackProperties playbackProperties =
Assertions.checkNotNull(exoplayerMediaItem.playbackProperties);
Assertions.checkNotNull(exoPlayerMediaItem.playbackProperties);
@Nullable Object tag = playbackProperties.tag;
if (!(tag instanceof androidx.media2.common.MediaItem)) {
throw new IllegalStateException(
"MediaItem tag must be an instance of androidx.media2.common.MediaItem");
if (tag instanceof androidx.media2.common.MediaItem) {
return (androidx.media2.common.MediaItem) tag;
}
return (androidx.media2.common.MediaItem) tag;
return new UriMediaItem.Builder(playbackProperties.uri).build();
}
}

View File

@ -33,5 +33,5 @@ public interface MediaItemConverter {
* Converts {@link MediaItem ExoPlayer MediaItem} to {@link androidx.media2.common.MediaItem
* AndroidX MediaItem}.
*/
androidx.media2.common.MediaItem convertToAndroidXMediaItem(MediaItem exoplayerMediaItem);
androidx.media2.common.MediaItem convertToAndroidXMediaItem(MediaItem exoPlayerMediaItem);
}

View File

@ -81,19 +81,19 @@ import java.util.List;
/** Called when the player encounters an error. */
void onError(@Nullable androidx.media2.common.MediaItem androidXMediaItem);
/** Called when the playlist is changed */
/** Called when the playlist is changed. */
void onPlaylistChanged();
/** Called when the shuffle mode is changed */
/** Called when the shuffle mode is changed. */
void onShuffleModeChanged(int shuffleMode);
/** Called when the repeat mode is changed */
/** Called when the repeat mode is changed. */
void onRepeatModeChanged(int repeatMode);
/** Called when the audio attributes is changed */
/** Called when the audio attributes is changed. */
void onAudioAttributesChanged(AudioAttributesCompat audioAttributes);
/** Called when the playback speed is changed */
/** Called when the playback speed is changed. */
void onPlaybackSpeedChanged(float playbackSpeed);
}
@ -108,14 +108,15 @@ import java.util.List;
private final ControlDispatcher controlDispatcher;
private final ComponentListener componentListener;
private final List<androidx.media2.common.MediaItem> cachedPlaylist;
@Nullable private MediaMetadata playlistMetadata;
private final List<MediaItem> cachedMediaItems;
// These should be only updated in TimelineChanges.
private final List<androidx.media2.common.MediaItem> androidXPlaylist;
private final List<MediaItem> exoPlayerPlaylist;
private boolean prepared;
private boolean rebuffering;
private int currentWindowIndex;
private boolean loggedUnexpectedTimelineChanges;
private boolean ignoreTimelineUpdates;
/**
@ -146,9 +147,14 @@ import java.util.List;
handler = new PlayerHandler(player.getApplicationLooper());
pollBufferRunnable = new PollBufferRunnable();
cachedPlaylist = new ArrayList<>();
cachedMediaItems = new ArrayList<>();
androidXPlaylist = new ArrayList<>();
exoPlayerPlaylist = new ArrayList<>();
currentWindowIndex = C.INDEX_UNSET;
prepared = player.getPlaybackState() != Player.STATE_IDLE;
rebuffering = player.getPlaybackState() == Player.STATE_BUFFERING;
updatePlaylist(player.getCurrentTimeline());
}
public boolean setMediaItem(androidx.media2.common.MediaItem androidXMediaItem) {
@ -163,62 +169,49 @@ import java.util.List;
Assertions.checkArgument(playlist.indexOf(androidXMediaItem) == i);
}
this.cachedPlaylist.clear();
this.cachedPlaylist.addAll(playlist);
this.playlistMetadata = metadata;
this.cachedMediaItems.clear();
List<MediaItem> exoplayerMediaItems = new ArrayList<>();
List<MediaItem> exoPlayerMediaItems = new ArrayList<>();
for (int i = 0; i < playlist.size(); i++) {
androidx.media2.common.MediaItem androidXMediaItem = playlist.get(i);
MediaItem exoplayerMediaItem =
MediaItem exoPlayerMediaItem =
Assertions.checkNotNull(
mediaItemConverter.convertToExoPlayerMediaItem(androidXMediaItem));
exoplayerMediaItems.add(exoplayerMediaItem);
exoPlayerMediaItems.add(exoPlayerMediaItem);
}
this.cachedMediaItems.addAll(exoplayerMediaItems);
player.setMediaItems(exoplayerMediaItems, /* resetPosition= */ true);
player.setMediaItems(exoPlayerMediaItems, /* resetPosition= */ true);
currentWindowIndex = getCurrentMediaItemIndex();
return true;
}
public boolean addPlaylistItem(int index, androidx.media2.common.MediaItem androidXMediaItem) {
Assertions.checkArgument(!cachedPlaylist.contains(androidXMediaItem));
index = Util.constrainValue(index, 0, cachedPlaylist.size());
Assertions.checkArgument(!androidXPlaylist.contains(androidXMediaItem));
index = Util.constrainValue(index, 0, androidXPlaylist.size());
cachedPlaylist.add(index, androidXMediaItem);
MediaItem exoplayerMediaItem =
MediaItem exoPlayerMediaItem =
Assertions.checkNotNull(mediaItemConverter.convertToExoPlayerMediaItem(androidXMediaItem));
cachedMediaItems.add(index, exoplayerMediaItem);
player.addMediaItem(index, exoplayerMediaItem);
player.addMediaItem(index, exoPlayerMediaItem);
return true;
}
public boolean removePlaylistItem(@IntRange(from = 0) int index) {
androidx.media2.common.MediaItem androidXMediaItemToRemove = cachedPlaylist.remove(index);
releaseMediaItem(androidXMediaItemToRemove);
cachedMediaItems.remove(index);
player.removeMediaItem(index);
return true;
}
public boolean replacePlaylistItem(
int index, androidx.media2.common.MediaItem androidXMediaItem) {
Assertions.checkArgument(!cachedPlaylist.contains(androidXMediaItem));
index = Util.constrainValue(index, 0, cachedPlaylist.size());
Assertions.checkArgument(!androidXPlaylist.contains(androidXMediaItem));
index = Util.constrainValue(index, 0, androidXPlaylist.size());
androidx.media2.common.MediaItem androidXMediaItemToRemove = cachedPlaylist.get(index);
cachedPlaylist.set(index, androidXMediaItem);
releaseMediaItem(androidXMediaItemToRemove);
MediaItem exoplayerMediaItemToAdd =
MediaItem exoPlayerMediaItemToAdd =
Assertions.checkNotNull(mediaItemConverter.convertToExoPlayerMediaItem(androidXMediaItem));
cachedMediaItems.set(index, exoplayerMediaItemToAdd);
ignoreTimelineUpdates = true;
player.removeMediaItem(index);
ignoreTimelineUpdates = false;
player.addMediaItem(index, exoplayerMediaItemToAdd);
player.addMediaItem(index, exoPlayerMediaItemToAdd);
return true;
}
@ -272,8 +265,8 @@ import java.util.List;
}
@Nullable
public List<androidx.media2.common.MediaItem> getCachedPlaylist() {
return new ArrayList<>(cachedPlaylist);
public List<androidx.media2.common.MediaItem> getPlaylist() {
return new ArrayList<>(androidXPlaylist);
}
@Nullable
@ -290,7 +283,7 @@ import java.util.List;
}
public int getCurrentMediaItemIndex() {
return cachedPlaylist.isEmpty() ? C.INDEX_UNSET : player.getCurrentWindowIndex();
return androidXPlaylist.isEmpty() ? C.INDEX_UNSET : player.getCurrentWindowIndex();
}
public int getPreviousMediaItemIndex() {
@ -304,7 +297,7 @@ import java.util.List;
@Nullable
public androidx.media2.common.MediaItem getCurrentMediaItem() {
int index = getCurrentMediaItemIndex();
return (index != C.INDEX_UNSET) ? cachedPlaylist.get(index) : null;
return (index != C.INDEX_UNSET) ? androidXPlaylist.get(index) : null;
}
public boolean prepare() {
@ -427,7 +420,7 @@ import java.util.List;
}
public boolean canSkipToPlaylistItem() {
@Nullable List<androidx.media2.common.MediaItem> playlist = getCachedPlaylist();
@Nullable List<androidx.media2.common.MediaItem> playlist = getPlaylist();
return playlist != null && playlist.size() > 1;
}
@ -505,49 +498,50 @@ import java.util.List;
if (ignoreTimelineUpdates) {
return;
}
updateCachedPlaylistAndMediaItems(timeline);
if (!isExoPlayerMediaItemsChanged(timeline)) {
return;
}
updatePlaylist(timeline);
listener.onPlaylistChanged();
}
// Update cached playlist, if the ExoPlayer Player's Timeline is unexpectedly changed without
// using SessionPlayer interface.
private void updateCachedPlaylistAndMediaItems(Timeline currentTimeline) {
// Check whether ExoPlayer media items are the same as expected.
// Check whether Timeline is changed by media item changes or not
private boolean isExoPlayerMediaItemsChanged(Timeline timeline) {
if (exoPlayerPlaylist.size() != timeline.getWindowCount()) {
return true;
}
Timeline.Window window = new Timeline.Window();
int windowCount = currentTimeline.getWindowCount();
int windowCount = timeline.getWindowCount();
for (int i = 0; i < windowCount; i++) {
currentTimeline.getWindow(i, window);
if (i >= cachedMediaItems.size()
|| !ObjectsCompat.equals(cachedMediaItems.get(i), window.mediaItem)) {
if (!loggedUnexpectedTimelineChanges) {
Log.w(TAG, "Timeline was unexpectedly changed. Playlist will be rebuilt.");
loggedUnexpectedTimelineChanges = true;
}
androidx.media2.common.MediaItem oldAndroidXMediaItem = cachedPlaylist.get(i);
releaseMediaItem(oldAndroidXMediaItem);
androidx.media2.common.MediaItem androidXMediaItem =
Assertions.checkNotNull(
mediaItemConverter.convertToAndroidXMediaItem(window.mediaItem));
if (i < cachedMediaItems.size()) {
cachedMediaItems.set(i, window.mediaItem);
cachedPlaylist.set(i, androidXMediaItem);
} else {
cachedMediaItems.add(window.mediaItem);
cachedPlaylist.add(androidXMediaItem);
}
timeline.getWindow(i, window);
if (!ObjectsCompat.equals(exoPlayerPlaylist.get(i), window.mediaItem)) {
return true;
}
}
if (cachedMediaItems.size() > windowCount) {
if (!loggedUnexpectedTimelineChanges) {
Log.w(TAG, "Timeline was unexpectedly changed. Playlist will be rebuilt.");
loggedUnexpectedTimelineChanges = true;
}
while (cachedMediaItems.size() > windowCount) {
cachedMediaItems.remove(windowCount);
cachedPlaylist.remove(windowCount);
}
return false;
}
private void updatePlaylist(Timeline timeline) {
List<androidx.media2.common.MediaItem> androidXMediaItemToBeRemoved =
new ArrayList<>(androidXPlaylist);
androidXPlaylist.clear();
exoPlayerPlaylist.clear();
Timeline.Window window = new Timeline.Window();
int windowCount = timeline.getWindowCount();
for (int i = 0; i < windowCount; i++) {
timeline.getWindow(i, window);
MediaItem exoPlayerMediaItem = window.mediaItem;
androidx.media2.common.MediaItem androidXMediaItem =
Assertions.checkNotNull(
mediaItemConverter.convertToAndroidXMediaItem(exoPlayerMediaItem));
exoPlayerPlaylist.add(exoPlayerMediaItem);
androidXPlaylist.add(androidXMediaItem);
androidXMediaItemToBeRemoved.remove(androidXMediaItem);
}
for (androidx.media2.common.MediaItem item : androidXMediaItemToBeRemoved) {
releaseMediaItem(item);
}
}

View File

@ -41,7 +41,6 @@ import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import org.checkerframework.checker.initialization.qual.Initialized;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/**
@ -95,7 +94,6 @@ public final class SessionPlayerConnector extends SessionPlayer {
// Should be only accessed on the executor, which is currently single-threaded.
@Nullable private MediaItem currentMediaItem;
@Nullable private List<MediaItem> currentPlaylist;
/**
* Creates an instance using {@link DefaultControlDispatcher} to dispatch player commands.
@ -124,19 +122,8 @@ public final class SessionPlayerConnector extends SessionPlayer {
taskHandler = new PlayerHandler(player.getApplicationLooper());
taskHandlerExecutor = taskHandler::postOrRun;
ExoPlayerWrapperListener playerListener = new ExoPlayerWrapperListener();
PlayerWrapper playerWrapper =
new PlayerWrapper(playerListener, player, mediaItemConverter, controlDispatcher);
this.player = playerWrapper;
this.player = new PlayerWrapper(playerListener, player, mediaItemConverter, controlDispatcher);
playerCommandQueue = new PlayerCommandQueue(this.player, taskHandler);
@SuppressWarnings("assignment.type.incompatible")
@Initialized
SessionPlayerConnector initializedThis = this;
initializedThis.<Void>runPlayerCallableBlocking(
/* callable= */ () -> {
playerWrapper.reset();
return null;
});
}
@Override
@ -258,7 +245,6 @@ public final class SessionPlayerConnector extends SessionPlayer {
ListenableFuture<PlayerResult> result =
playerCommandQueue.addCommand(
PlayerCommandQueue.COMMAND_CODE_PLAYER_SET_MEDIA_ITEM, () -> player.setMediaItem(item));
result.addListener(this::handlePlaylistChangedOnHandler, taskHandlerExecutor);
return result;
}
@ -281,7 +267,6 @@ public final class SessionPlayerConnector extends SessionPlayer {
playerCommandQueue.addCommand(
PlayerCommandQueue.COMMAND_CODE_PLAYER_SET_PLAYLIST,
/* command= */ () -> player.setPlaylist(playlist, metadata));
result.addListener(this::handlePlaylistChangedOnHandler, taskHandlerExecutor);
return result;
}
@ -294,7 +279,6 @@ public final class SessionPlayerConnector extends SessionPlayer {
playerCommandQueue.addCommand(
PlayerCommandQueue.COMMAND_CODE_PLAYER_ADD_PLAYLIST_ITEM,
/* command= */ () -> player.addPlaylistItem(index, item));
result.addListener(this::handlePlaylistChangedOnHandler, taskHandlerExecutor);
return result;
}
@ -305,7 +289,6 @@ public final class SessionPlayerConnector extends SessionPlayer {
playerCommandQueue.addCommand(
PlayerCommandQueue.COMMAND_CODE_PLAYER_REMOVE_PLAYLIST_ITEM,
/* command= */ () -> player.removePlaylistItem(index));
result.addListener(this::handlePlaylistChangedOnHandler, taskHandlerExecutor);
return result;
}
@ -318,7 +301,6 @@ public final class SessionPlayerConnector extends SessionPlayer {
playerCommandQueue.addCommand(
PlayerCommandQueue.COMMAND_CODE_PLAYER_REPLACE_PLAYLIST_ITEM,
/* command= */ () -> player.replacePlaylistItem(index, item));
result.addListener(this::handlePlaylistChangedOnHandler, taskHandlerExecutor);
return result;
}
@ -385,7 +367,7 @@ public final class SessionPlayerConnector extends SessionPlayer {
@Override
@Nullable
public List<MediaItem> getPlaylist() {
return runPlayerCallableBlockingWithNullOnException(/* callable= */ player::getCachedPlaylist);
return runPlayerCallableBlockingWithNullOnException(/* callable= */ player::getPlaylist);
}
@Override
@ -558,25 +540,18 @@ public final class SessionPlayerConnector extends SessionPlayer {
}
private void handlePlaylistChangedOnHandler() {
List<MediaItem> currentPlaylist = player.getCachedPlaylist();
boolean notifyCurrentPlaylist = !ObjectsCompat.equals(this.currentPlaylist, currentPlaylist);
this.currentPlaylist = currentPlaylist;
List<MediaItem> currentPlaylist = player.getPlaylist();
MediaMetadata playlistMetadata = player.getPlaylistMetadata();
MediaItem currentMediaItem = player.getCurrentMediaItem();
boolean notifyCurrentMediaItem = !ObjectsCompat.equals(this.currentMediaItem, currentMediaItem);
this.currentMediaItem = currentMediaItem;
if (!notifyCurrentMediaItem && !notifyCurrentPlaylist) {
return;
}
long currentPosition = getCurrentPosition();
notifySessionPlayerCallback(
callback -> {
if (notifyCurrentPlaylist) {
callback.onPlaylistChanged(
SessionPlayerConnector.this, currentPlaylist, playlistMetadata);
}
callback.onPlaylistChanged(
SessionPlayerConnector.this, currentPlaylist, playlistMetadata);
if (notifyCurrentMediaItem) {
Assertions.checkNotNull(
currentMediaItem, "PlaylistManager#currentMediaItem() cannot be changed to null");