diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 06457cd7f5..1851156d92 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -67,6 +67,11 @@ configure this value. * Fix issue where notifications reappear after they have been dismissed by the user ([#2302](https://github.com/androidx/media/issues/2302)). + * Fix a bug where the `PlayerWrapper` returned a single-item timeline when + the wrapped player is actually empty. This happened when the wrapped + player doesn't have `COMMAND_GET_TIMELINE` available while + `COMMAND_GET_CURRENT_MEDIA_ITEM` is available and the wrapped player is + empty ([#2320](https://github.com/androidx/media/issues/2320)). * UI: * Enable `PlayerSurface` to work with `ExoPlayer.setVideoEffects` and `CompositionPlayer`. diff --git a/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java b/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java index d1cc1e0ad4..b493f2bf25 100644 --- a/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java +++ b/libraries/session/src/main/java/androidx/media3/session/PlayerWrapper.java @@ -710,7 +710,9 @@ import java.util.List; if (isCommandAvailable(COMMAND_GET_TIMELINE)) { return getCurrentTimeline(); } else if (isCommandAvailable(COMMAND_GET_CURRENT_MEDIA_ITEM)) { - return new CurrentMediaItemOnlyTimeline(this); + return getCurrentTimeline().isEmpty() + ? Timeline.EMPTY + : new CurrentMediaItemOnlyTimeline(this); } return Timeline.EMPTY; } diff --git a/libraries/session/src/test/java/androidx/media3/session/PlayerWrapperTest.java b/libraries/session/src/test/java/androidx/media3/session/PlayerWrapperTest.java index 0679f05915..5ea27d854a 100644 --- a/libraries/session/src/test/java/androidx/media3/session/PlayerWrapperTest.java +++ b/libraries/session/src/test/java/androidx/media3/session/PlayerWrapperTest.java @@ -22,6 +22,8 @@ import static org.mockito.Mockito.when; import android.os.Bundle; import android.os.Looper; import androidx.media3.common.Player; +import androidx.media3.common.Timeline; +import androidx.media3.test.utils.FakeTimeline; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.common.collect.ImmutableList; import org.junit.Before; @@ -57,6 +59,52 @@ public class PlayerWrapperTest { when(player.getApplicationLooper()).thenReturn(Looper.myLooper()); } + @Test + public void + getCurrentTimelineWithCommandCheck_withoutCommandGetTimelineAndGetCurrentMediaItem_isEmpty() { + when(player.isCommandAvailable(Player.COMMAND_GET_TIMELINE)).thenReturn(false); + when(player.isCommandAvailable(Player.COMMAND_GET_CURRENT_MEDIA_ITEM)).thenReturn(false); + when(player.getCurrentTimeline()).thenReturn(new FakeTimeline(/* windowCount= */ 3)); + + Timeline currentTimeline = playerWrapper.getCurrentTimelineWithCommandCheck(); + + assertThat(currentTimeline.isEmpty()).isTrue(); + } + + @Test + public void getCurrentTimelineWithCommandCheck_withoutCommandGetTimelineWhenEmpty_isEmpty() { + when(player.isCommandAvailable(Player.COMMAND_GET_TIMELINE)).thenReturn(false); + when(player.isCommandAvailable(Player.COMMAND_GET_CURRENT_MEDIA_ITEM)).thenReturn(true); + when(player.getCurrentTimeline()).thenReturn(Timeline.EMPTY); + + Timeline currentTimeline = playerWrapper.getCurrentTimelineWithCommandCheck(); + + assertThat(currentTimeline.isEmpty()).isTrue(); + } + + @Test + public void + getCurrentTimelineWithCommandCheck_withoutCommandGetTimelineWhenMultipleItems_hasSingleItemTimeline() { + when(player.isCommandAvailable(Player.COMMAND_GET_TIMELINE)).thenReturn(false); + when(player.isCommandAvailable(Player.COMMAND_GET_CURRENT_MEDIA_ITEM)).thenReturn(true); + when(player.getCurrentTimeline()).thenReturn(new FakeTimeline(/* windowCount= */ 3)); + + Timeline currentTimeline = playerWrapper.getCurrentTimelineWithCommandCheck(); + + assertThat(currentTimeline.getWindowCount()).isEqualTo(1); + } + + @Test + public void getCurrentTimelineWithCommandCheck_withCommandGetTimeline_returnOriginalTimeline() { + when(player.isCommandAvailable(Player.COMMAND_GET_TIMELINE)).thenReturn(true); + when(player.isCommandAvailable(Player.COMMAND_GET_CURRENT_MEDIA_ITEM)).thenReturn(false); + when(player.getCurrentTimeline()).thenReturn(new FakeTimeline(/* windowCount= */ 3)); + + Timeline currentTimeline = playerWrapper.getCurrentTimelineWithCommandCheck(); + + assertThat(currentTimeline.getWindowCount()).isEqualTo(3); + } + @Test public void createSessionPositionInfoForBundling() { int testAdGroupIndex = 12;