diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/preload/PreloadMediaSource.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/preload/PreloadMediaSource.java index d6065d37fe..ebc199900f 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/preload/PreloadMediaSource.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/source/preload/PreloadMediaSource.java @@ -216,6 +216,7 @@ public final class PreloadMediaSource extends WrappingMediaSource { @Nullable private Timeline timeline; @Nullable private Pair preloadingMediaPeriodAndKey; @Nullable private Pair playingPreloadedMediaPeriodAndId; + private boolean onSourcePreparedNotified; private boolean onUsedByPlayerNotified; private PreloadMediaSource( @@ -250,6 +251,7 @@ public final class PreloadMediaSource extends WrappingMediaSource { () -> { preloadCalled = true; this.startPositionUs = startPositionUs; + onSourcePreparedNotified = false; if (isUsedByPlayer()) { notifyOnUsedByPlayer(); } else { @@ -291,7 +293,11 @@ public final class PreloadMediaSource extends WrappingMediaSource { protected void onChildSourceInfoRefreshed(Timeline newTimeline) { this.timeline = newTimeline; refreshSourceInfo(newTimeline); - if (isUsedByPlayer() || !preloadControl.onSourcePrepared(PreloadMediaSource.this)) { + if (isUsedByPlayer() || onSourcePreparedNotified) { + return; + } + onSourcePreparedNotified = true; + if (!preloadControl.onSourcePrepared(this)) { return; } Pair periodPosition = @@ -377,6 +383,7 @@ public final class PreloadMediaSource extends WrappingMediaSource { () -> { preloadCalled = false; startPositionUs = C.TIME_UNSET; + onSourcePreparedNotified = false; if (preloadingMediaPeriodAndKey != null) { mediaSource.releasePeriod(preloadingMediaPeriodAndKey.first.mediaPeriod); preloadingMediaPeriodAndKey = null; @@ -397,10 +404,10 @@ public final class PreloadMediaSource extends WrappingMediaSource { @Override public void onPrepared(MediaPeriod mediaPeriod) { + prepared = true; if (isUsedByPlayer()) { return; } - prepared = true; PreloadMediaPeriod preloadMediaPeriod = (PreloadMediaPeriod) mediaPeriod; TrackGroupArray trackGroups = preloadMediaPeriod.getTrackGroups(); @Nullable TrackSelectorResult trackSelectorResult = null; diff --git a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/preload/PreloadMediaSourceTest.java b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/preload/PreloadMediaSourceTest.java index f60a17f38c..990dd59c4c 100644 --- a/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/preload/PreloadMediaSourceTest.java +++ b/libraries/exoplayer/src/test/java/androidx/media3/exoplayer/source/preload/PreloadMediaSourceTest.java @@ -72,6 +72,7 @@ import androidx.media3.test.utils.FakeVideoRenderer; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.junit.Before; import org.junit.Test; @@ -107,7 +108,7 @@ public final class PreloadMediaSourceTest { @Test public void preload_loadPeriodToTargetPreloadPosition() throws Exception { - AtomicBoolean onSourcePreparedCalled = new AtomicBoolean(); + AtomicInteger onSourcePreparedCounter = new AtomicInteger(); AtomicBoolean onTracksSelectedCalled = new AtomicBoolean(); AtomicBoolean onContinueLoadingStopped = new AtomicBoolean(); AtomicReference preloadMediaSourceReference = new AtomicReference<>(); @@ -116,7 +117,7 @@ public final class PreloadMediaSourceTest { new PreloadMediaSource.PreloadControl() { @Override public boolean onSourcePrepared(PreloadMediaSource mediaSource) { - onSourcePreparedCalled.set(true); + onSourcePreparedCounter.addAndGet(1); return true; } @@ -167,7 +168,7 @@ public final class PreloadMediaSourceTest { preloadMediaSource.preload(/* startPositionUs= */ 0L); runMainLooperUntil(onContinueLoadingStopped::get); - assertThat(onSourcePreparedCalled.get()).isTrue(); + assertThat(onSourcePreparedCounter.get()).isEqualTo(1); assertThat(onTracksSelectedCalled.get()).isTrue(); assertThat(onUsedByPlayerCalled.get()).isFalse(); assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); @@ -175,7 +176,7 @@ public final class PreloadMediaSourceTest { @Test public void preload_stopWhenTracksSelectedByPreloadControl() throws Exception { - AtomicBoolean onSourcePreparedCalled = new AtomicBoolean(); + AtomicInteger onSourcePreparedCounter = new AtomicInteger(); AtomicBoolean onTracksSelectedCalled = new AtomicBoolean(); AtomicReference preloadMediaSourceReference = new AtomicReference<>(); AtomicBoolean onContinueLoadingRequestedCalled = new AtomicBoolean(); @@ -184,7 +185,7 @@ public final class PreloadMediaSourceTest { new PreloadMediaSource.PreloadControl() { @Override public boolean onSourcePrepared(PreloadMediaSource mediaSource) { - onSourcePreparedCalled.set(true); + onSourcePreparedCounter.addAndGet(1); return true; } @@ -232,7 +233,7 @@ public final class PreloadMediaSourceTest { preloadMediaSource.preload(/* startPositionUs= */ 0L); runMainLooperUntil(onTracksSelectedCalled::get); - assertThat(onSourcePreparedCalled.get()).isTrue(); + assertThat(onSourcePreparedCounter.get()).isEqualTo(1); assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); assertThat(onContinueLoadingRequestedCalled.get()).isFalse(); assertThat(onUsedByPlayerCalled.get()).isFalse(); @@ -240,7 +241,7 @@ public final class PreloadMediaSourceTest { @Test public void preload_stopWhenSourcePreparedByPreloadControl() throws Exception { - AtomicBoolean onSourcePreparedCalled = new AtomicBoolean(); + AtomicInteger onSourcePreparedCounter = new AtomicInteger(); AtomicReference preloadMediaSourceReference = new AtomicReference<>(); AtomicBoolean onTracksSelectedCalled = new AtomicBoolean(); AtomicBoolean onContinueLoadingRequestedCalled = new AtomicBoolean(); @@ -250,7 +251,7 @@ public final class PreloadMediaSourceTest { @Override public boolean onSourcePrepared(PreloadMediaSource mediaSource) { preloadMediaSourceReference.set(mediaSource); - onSourcePreparedCalled.set(true); + onSourcePreparedCounter.addAndGet(1); return false; } @@ -294,9 +295,10 @@ public final class PreloadMediaSourceTest { .build()); preloadMediaSource.preload(/* startPositionUs= */ 0L); - runMainLooperUntil(onSourcePreparedCalled::get); + shadowOf(Looper.getMainLooper()).idle(); assertThat(preloadMediaSourceReference.get()).isSameInstanceAs(preloadMediaSource); + assertThat(onSourcePreparedCounter.get()).isEqualTo(1); assertThat(onTracksSelectedCalled.get()).isFalse(); assertThat(onContinueLoadingRequestedCalled.get()).isFalse(); assertThat(onUsedByPlayerCalled.get()).isFalse(); @@ -366,7 +368,7 @@ public final class PreloadMediaSourceTest { @Test public void preload_loadToTheEndOfSource() throws Exception { - AtomicBoolean onSourcePreparedCalled = new AtomicBoolean(); + AtomicInteger onSourcePreparedCounter = new AtomicInteger(); AtomicBoolean onTracksSelectedCalled = new AtomicBoolean(); AtomicBoolean onContinueLoadingRequestedCalled = new AtomicBoolean(); AtomicBoolean onLoadedToTheEndOfSourceCalled = new AtomicBoolean(); @@ -375,7 +377,7 @@ public final class PreloadMediaSourceTest { new PreloadMediaSource.PreloadControl() { @Override public boolean onSourcePrepared(PreloadMediaSource mediaSource) { - onSourcePreparedCalled.set(true); + onSourcePreparedCounter.addAndGet(1); return true; } @@ -432,7 +434,7 @@ public final class PreloadMediaSourceTest { preloadMediaSource.preload(/* startPositionUs= */ 0L); runMainLooperUntil(onLoadedToTheEndOfSourceCalled::get); - assertThat(onSourcePreparedCalled.get()).isTrue(); + assertThat(onSourcePreparedCounter.get()).isEqualTo(1); assertThat(onTracksSelectedCalled.get()).isTrue(); assertThat(onContinueLoadingRequestedCalled.get()).isTrue(); assertThat(onUsedByPlayerCalled.get()).isFalse();