From aac53cac56143e96bebcc0243f74cebe3e52b817 Mon Sep 17 00:00:00 2001 From: tonihei Date: Tue, 21 Nov 2017 01:33:48 -0800 Subject: [PATCH] Add reason to onTimelineChanged. Currently onTimelineChanged doesn't allow to distinguish easily between the different reasons why it's being called. Especially, finding out whether a new media source has been prepared or the current source refreshed dynamically was impossible without tightly coupling the player operations with the listener. The new reasons provide this disdinction by either indicating a newly initialized media source, a dynamic update to an existing timeline or manifest, or a reset of the player (which usually results in an empty timeline). The original onTimelineChanged method without reason is kept in the DefaultEventListener as deprecated to prevent the need to update all existing listeners in one go. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=176478701 --- RELEASENOTES.md | 2 + .../android/exoplayer2/demo/EventLogger.java | 20 ++++++++- .../exoplayer2/ext/cast/CastPlayer.java | 7 +++- .../exoplayer2/ext/ima/ImaAdsLoader.java | 7 ++-- .../ext/leanback/LeanbackPlayerAdapter.java | 4 +- .../mediasession/MediaSessionConnector.java | 3 +- .../android/exoplayer2/ExoPlayerTest.java | 30 +++++++++++++- .../android/exoplayer2/ExoPlayerImpl.java | 12 ++++-- .../com/google/android/exoplayer2/Player.java | 41 +++++++++++++++++-- .../exoplayer2/ui/PlaybackControlView.java | 5 ++- .../android/exoplayer2/testutil/Action.java | 5 ++- .../testutil/ExoPlayerTestRunner.java | 18 +++++++- .../testutil/FakeSimpleExoPlayer.java | 3 +- 13 files changed, 136 insertions(+), 21 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 6438cbdd68..c01f2c29ee 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -22,6 +22,8 @@ use this with `FfmpegAudioRenderer`. * Support extraction and decoding of Dolby Atmos ([#2465](https://github.com/google/ExoPlayer/issues/2465)). +* Added a reason to `EventListener.onTimelineChanged` to distinguish between + initial preparation, reset and dynamic updates. ### 2.6.0 ### diff --git a/demos/main/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java b/demos/main/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java index 9233b016f5..473a0d3441 100644 --- a/demos/main/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java +++ b/demos/main/src/main/java/com/google/android/exoplayer2/demo/EventLogger.java @@ -116,10 +116,12 @@ import java.util.Locale; } @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { + public void onTimelineChanged(Timeline timeline, Object manifest, + @Player.TimelineChangeReason int reason) { int periodCount = timeline.getPeriodCount(); int windowCount = timeline.getWindowCount(); - Log.d(TAG, "sourceInfo [periodCount=" + periodCount + ", windowCount=" + windowCount); + Log.d(TAG, "timelineChanged [periodCount=" + periodCount + ", windowCount=" + windowCount + + ", reason=" + getTimelineChangeReasonString(reason)); for (int i = 0; i < Math.min(periodCount, MAX_TIMELINE_ITEM_LINES); i++) { timeline.getPeriod(i, period); Log.d(TAG, " " + "period [" + getTimeString(period.getDurationMs()) + "]"); @@ -507,4 +509,18 @@ import java.util.Locale; return "?"; } } + + private static String getTimelineChangeReasonString(@Player.TimelineChangeReason int reason) { + switch (reason) { + case Player.TIMELINE_CHANGE_REASON_PREPARED: + return "PREPARED"; + case Player.TIMELINE_CHANGE_REASON_RESET: + return "RESET"; + case Player.TIMELINE_CHANGE_REASON_DYNAMIC: + return "DYNAMIC"; + default: + return "?"; + } + } + } diff --git a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java index 9a8986409a..32e064e834 100644 --- a/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java +++ b/extensions/cast/src/main/java/com/google/android/exoplayer2/ext/cast/CastPlayer.java @@ -116,6 +116,7 @@ public final class CastPlayer implements Player { private int pendingSeekCount; private int pendingSeekWindowIndex; private long pendingSeekPositionMs; + private boolean waitingForInitialTimeline; /** * @param castContext The context from which the cast session is obtained. @@ -170,6 +171,7 @@ public final class CastPlayer implements Player { public PendingResult loadItems(MediaQueueItem[] items, int startIndex, long positionMs, @RepeatMode int repeatMode) { if (remoteMediaClient != null) { + waitingForInitialTimeline = true; return remoteMediaClient.queueLoad(items, startIndex, getCastRepeatMode(repeatMode), positionMs, null); } @@ -556,8 +558,11 @@ public final class CastPlayer implements Player { private void maybeUpdateTimelineAndNotify() { if (updateTimeline()) { + @Player.TimelineChangeReason int reason = waitingForInitialTimeline + ? Player.TIMELINE_CHANGE_REASON_PREPARED : Player.TIMELINE_CHANGE_REASON_DYNAMIC; + waitingForInitialTimeline = false; for (EventListener listener : listeners) { - listener.onTimelineChanged(currentTimeline, null); + listener.onTimelineChanged(currentTimeline, null, reason); } } } diff --git a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java index 5b61db0264..fe6a6d6196 100644 --- a/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java +++ b/extensions/ima/src/main/java/com/google/android/exoplayer2/ext/ima/ImaAdsLoader.java @@ -523,9 +523,10 @@ public final class ImaAdsLoader extends Player.DefaultEventListener implements A // Player.EventListener implementation. @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { - if (timeline.isEmpty()) { - // The player is being re-prepared and this source will be released. + public void onTimelineChanged(Timeline timeline, Object manifest, + @Player.TimelineChangeReason int reason) { + if (reason == Player.TIMELINE_CHANGE_REASON_RESET) { + // The player is being reset and this source will be released. return; } Assertions.checkArgument(timeline.getPeriodCount() == 1); diff --git a/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java b/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java index 510ed9cf4f..c9ed54398e 100644 --- a/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java +++ b/extensions/leanback/src/main/java/com/google/android/exoplayer2/ext/leanback/LeanbackPlayerAdapter.java @@ -32,6 +32,7 @@ import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayerLibraryInfo; import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player.DiscontinuityReason; +import com.google.android.exoplayer2.Player.TimelineChangeReason; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.util.ErrorMessageProvider; @@ -258,7 +259,8 @@ public final class LeanbackPlayerAdapter extends PlayerAdapter { } @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { + public void onTimelineChanged(Timeline timeline, Object manifest, + @TimelineChangeReason int reason) { Callback callback = getCallback(); callback.onDurationChanged(LeanbackPlayerAdapter.this); callback.onCurrentPositionChanged(LeanbackPlayerAdapter.this); diff --git a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java index aa007ea1d6..d80487f2bd 100644 --- a/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java +++ b/extensions/mediasession/src/main/java/com/google/android/exoplayer2/ext/mediasession/MediaSessionConnector.java @@ -628,7 +628,8 @@ public final class MediaSessionConnector { private int currentWindowCount; @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { + public void onTimelineChanged(Timeline timeline, Object manifest, + @Player.TimelineChangeReason int reason) { int windowCount = player.getCurrentTimeline().getWindowCount(); int windowIndex = player.getCurrentWindowIndex(); if (queueNavigator != null) { diff --git a/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java index f0f1c23c2b..59a58a4912 100644 --- a/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java +++ b/library/core/src/androidTest/java/com/google/android/exoplayer2/ExoPlayerTest.java @@ -17,6 +17,7 @@ package com.google.android.exoplayer2; import com.google.android.exoplayer2.source.ConcatenatingMediaSource; import com.google.android.exoplayer2.source.MediaSource; +import com.google.android.exoplayer2.source.MediaSource.Listener; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; import com.google.android.exoplayer2.testutil.ActionSchedule; @@ -28,6 +29,7 @@ import com.google.android.exoplayer2.testutil.FakeMediaSource; import com.google.android.exoplayer2.testutil.FakeRenderer; import com.google.android.exoplayer2.testutil.FakeShuffleOrder; import com.google.android.exoplayer2.testutil.FakeTimeline; +import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition; import com.google.android.exoplayer2.testutil.FakeTrackSelection; import com.google.android.exoplayer2.testutil.FakeTrackSelector; import com.google.android.exoplayer2.upstream.Allocator; @@ -59,7 +61,7 @@ public final class ExoPlayerTest extends TestCase { .setTimeline(timeline).setRenderers(renderer) .build().start().blockUntilEnded(TIMEOUT_MS); testRunner.assertNoPositionDiscontinuities(); - testRunner.assertTimelinesEqual(); + testRunner.assertTimelinesEqual(timeline); assertEquals(0, renderer.formatReadCount); assertEquals(0, renderer.bufferReadCount); assertFalse(renderer.isEnded); @@ -78,6 +80,7 @@ public final class ExoPlayerTest extends TestCase { testRunner.assertNoPositionDiscontinuities(); testRunner.assertTimelinesEqual(timeline); testRunner.assertManifestsEqual(manifest); + testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED); testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT))); assertEquals(1, renderer.formatReadCount); assertEquals(1, renderer.bufferReadCount); @@ -97,6 +100,7 @@ public final class ExoPlayerTest extends TestCase { Player.DISCONTINUITY_REASON_PERIOD_TRANSITION, Player.DISCONTINUITY_REASON_PERIOD_TRANSITION); testRunner.assertTimelinesEqual(timeline); + testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED); assertEquals(3, renderer.formatReadCount); assertEquals(1, renderer.bufferReadCount); assertTrue(renderer.isEnded); @@ -210,6 +214,8 @@ public final class ExoPlayerTest extends TestCase { // info refresh from the second source was suppressed as we re-prepared with the third source. testRunner.assertTimelinesEqual(timeline, Timeline.EMPTY, timeline); testRunner.assertManifestsEqual(firstSourceManifest, null, thirdSourceManifest); + testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED, + Player.TIMELINE_CHANGE_REASON_RESET, Player.TIMELINE_CHANGE_REASON_PREPARED); testRunner.assertTrackGroupsEqual(new TrackGroupArray(new TrackGroup(Builder.VIDEO_FORMAT))); assertEquals(1, renderer.formatReadCount); assertEquals(1, renderer.bufferReadCount); @@ -243,6 +249,7 @@ public final class ExoPlayerTest extends TestCase { Player.DISCONTINUITY_REASON_PERIOD_TRANSITION, Player.DISCONTINUITY_REASON_PERIOD_TRANSITION); testRunner.assertTimelinesEqual(timeline); + testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED); assertTrue(renderer.isEnded); } @@ -513,4 +520,25 @@ public final class ExoPlayerTest extends TestCase { assertEquals(3, numSelectionsEnabled); } + public void testDynamicTimelineChangeReason() throws Exception { + Timeline timeline1 = new FakeTimeline(new TimelineWindowDefinition(false, false, 100000)); + final Timeline timeline2 = new FakeTimeline(new TimelineWindowDefinition(false, false, 20000)); + final FakeMediaSource mediaSource = new FakeMediaSource(timeline1, null, Builder.VIDEO_FORMAT); + ActionSchedule actionSchedule = new ActionSchedule.Builder("testDynamicTimelineChangeReason") + .waitForTimelineChanged(timeline1) + .executeRunnable(new Runnable() { + @Override + public void run() { + mediaSource.setNewSourceInfo(timeline2, null); + } + }) + .build(); + ExoPlayerTestRunner testRunner = new ExoPlayerTestRunner.Builder() + .setMediaSource(mediaSource).setActionSchedule(actionSchedule) + .build().start().blockUntilEnded(TIMEOUT_MS); + testRunner.assertTimelinesEqual(timeline1, timeline2); + testRunner.assertTimelineChangeReasonsEqual(Player.TIMELINE_CHANGE_REASON_PREPARED, + Player.TIMELINE_CHANGE_REASON_DYNAMIC); + } + } diff --git a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java index ff00f9de91..77131f5ded 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/ExoPlayerImpl.java @@ -56,6 +56,7 @@ import java.util.concurrent.CopyOnWriteArraySet; private int playbackState; private int pendingSeekAcks; private int pendingPrepareAcks; + private boolean waitingForInitialTimeline; private boolean isLoading; private TrackGroupArray trackGroups; private TrackSelectionArray trackSelections; @@ -146,7 +147,8 @@ import java.util.concurrent.CopyOnWriteArraySet; if (!playbackInfo.timeline.isEmpty() || playbackInfo.manifest != null) { playbackInfo = playbackInfo.copyWithTimeline(Timeline.EMPTY, null); for (Player.EventListener listener : listeners) { - listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest); + listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest, + Player.TIMELINE_CHANGE_REASON_RESET); } } if (tracksSelected) { @@ -159,6 +161,7 @@ import java.util.concurrent.CopyOnWriteArraySet; } } } + waitingForInitialTimeline = true; pendingPrepareAcks++; internalPlayer.prepare(mediaSource, resetPosition); } @@ -532,9 +535,12 @@ import java.util.concurrent.CopyOnWriteArraySet; maskingWindowIndex = 0; maskingWindowPositionMs = 0; } - if (timelineOrManifestChanged) { + if (timelineOrManifestChanged || waitingForInitialTimeline) { + @Player.TimelineChangeReason int reason = waitingForInitialTimeline + ? Player.TIMELINE_CHANGE_REASON_PREPARED : Player.TIMELINE_CHANGE_REASON_DYNAMIC; + waitingForInitialTimeline = false; for (Player.EventListener listener : listeners) { - listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest); + listener.onTimelineChanged(playbackInfo.timeline, playbackInfo.manifest, reason); } } if (positionDiscontinuity) { diff --git a/library/core/src/main/java/com/google/android/exoplayer2/Player.java b/library/core/src/main/java/com/google/android/exoplayer2/Player.java index dc703f924a..77fced0832 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/Player.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/Player.java @@ -59,8 +59,9 @@ public interface Player { * * @param timeline The latest timeline. Never null, but may be empty. * @param manifest The latest manifest. May be null. + * @param reason The {@link TimelineChangeReason} responsible for this timeline change. */ - void onTimelineChanged(Timeline timeline, Object manifest); + void onTimelineChanged(Timeline timeline, Object manifest, @TimelineChangeReason int reason); /** * Called when the available or selected tracks change. @@ -118,7 +119,8 @@ public interface Player { * when the source introduces a discontinuity internally). *

* When a position discontinuity occurs as a result of a change to the timeline this method is - * not called. {@link #onTimelineChanged(Timeline, Object)} is called in this case. + * not called. {@link #onTimelineChanged(Timeline, Object, int)} is called in this + * case. * * @param reason The {@link DiscontinuityReason} responsible for the discontinuity. */ @@ -149,8 +151,10 @@ public interface Player { abstract class DefaultEventListener implements EventListener { @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { - // Do nothing. + public void onTimelineChanged(Timeline timeline, Object manifest, + @TimelineChangeReason int reason) { + // Call deprecated version. Otherwise, do nothing. + onTimelineChanged(timeline, manifest); } @Override @@ -198,6 +202,15 @@ public interface Player { // Do nothing. } + /** + * @deprecated Use {@link DefaultEventListener#onTimelineChanged(Timeline, Object, int)} + * instead. + */ + @Deprecated + public void onTimelineChanged(Timeline timeline, Object manifest) { + // Do nothing. + } + } /** @@ -264,6 +277,26 @@ public interface Player { */ int DISCONTINUITY_REASON_INTERNAL = 3; + /** + * Reasons for timeline and/or manifest changes. + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({TIMELINE_CHANGE_REASON_PREPARED, TIMELINE_CHANGE_REASON_RESET, + TIMELINE_CHANGE_REASON_DYNAMIC}) + public @interface TimelineChangeReason {} + /** + * Timeline and manifest changed as a result of a player initialization with new media. + */ + int TIMELINE_CHANGE_REASON_PREPARED = 0; + /** + * Timeline and manifest changed as a result of a player reset. + */ + int TIMELINE_CHANGE_REASON_RESET = 1; + /** + * Timeline or manifest changed as a result of an dynamic update introduced by the played media. + */ + int TIMELINE_CHANGE_REASON_DYNAMIC = 2; + /** * Register a listener to receive events from the player. The listener's methods will be called on * the thread that was used to construct the player. However, if the thread used to construct the diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java index a96ed3a622..751a6c81a9 100644 --- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java +++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlaybackControlView.java @@ -699,6 +699,8 @@ public class PlaybackControlView extends FrameLayout { repeatToggleButton.setImageDrawable(repeatAllButtonDrawable); repeatToggleButton.setContentDescription(repeatAllButtonContentDescription); break; + default: + // Never happens. } repeatToggleButton.setVisibility(View.VISIBLE); } @@ -1098,7 +1100,8 @@ public class PlaybackControlView extends FrameLayout { } @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { + public void onTimelineChanged(Timeline timeline, Object manifest, + @Player.TimelineChangeReason int reason) { updateNavigation(); updateTimeBarMode(); updateProgress(); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java index 2abe521883..357d69df38 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/Action.java @@ -304,7 +304,7 @@ public abstract class Action { } /** - * Waits for {@link Player.EventListener#onTimelineChanged(Timeline, Object)}. + * Waits for {@link Player.EventListener#onTimelineChanged(Timeline, Object, int)}. */ public static final class WaitForTimelineChanged extends Action { @@ -327,7 +327,8 @@ public abstract class Action { } Player.EventListener listener = new Player.DefaultEventListener() { @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { + public void onTimelineChanged(Timeline timeline, Object manifest, + @Player.TimelineChangeReason int reason) { if (timeline.equals(expectedTimeline)) { player.removeListener(this); nextAction.schedule(player, trackSelector, surface, handler); diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java index 6730bf1c7f..638ad9e12d 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/ExoPlayerTestRunner.java @@ -318,6 +318,7 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener { private final CountDownLatch endedCountDownLatch; private final LinkedList timelines; private final LinkedList manifests; + private final ArrayList timelineChangeReasons; private final LinkedList periodIndices; private final ArrayList discontinuityReasons; @@ -338,6 +339,7 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener { this.eventListener = eventListener; this.timelines = new LinkedList<>(); this.manifests = new LinkedList<>(); + this.timelineChangeReasons = new ArrayList<>(); this.periodIndices = new LinkedList<>(); this.discontinuityReasons = new ArrayList<>(); this.endedCountDownLatch = new CountDownLatch(1); @@ -430,6 +432,18 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener { } } + /** + * Asserts that the timeline change reasons reported by + * {@link Player.EventListener#onTimelineChanged(Timeline, Object, int)} are equal to the provided + * timeline change reasons. + */ + public void assertTimelineChangeReasonsEqual(@Player.TimelineChangeReason int... reasons) { + Assert.assertEquals(reasons.length, timelineChangeReasons.size()); + for (int i = 0; i < reasons.length; i++) { + Assert.assertEquals(reasons[i], (int) timelineChangeReasons.get(i)); + } + } + /** * Asserts that the last track group array reported by * {@link Player.EventListener#onTracksChanged(TrackGroupArray, TrackSelectionArray)} is equal to @@ -507,9 +521,11 @@ public final class ExoPlayerTestRunner extends Player.DefaultEventListener { // Player.EventListener @Override - public void onTimelineChanged(Timeline timeline, Object manifest) { + public void onTimelineChanged(Timeline timeline, Object manifest, + @Player.TimelineChangeReason int reason) { timelines.add(timeline); manifests.add(manifest); + timelineChangeReasons.add(reason); } @Override diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeSimpleExoPlayer.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeSimpleExoPlayer.java index 4a5beb0501..6dc9cf7fd8 100644 --- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeSimpleExoPlayer.java +++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/FakeSimpleExoPlayer.java @@ -340,7 +340,8 @@ public class FakeSimpleExoPlayer extends SimpleExoPlayer { FakeExoPlayer.this.durationUs = timeline.getPeriod(0, new Period()).durationUs; FakeExoPlayer.this.timeline = timeline; FakeExoPlayer.this.manifest = manifest; - eventListener.onTimelineChanged(timeline, manifest); + eventListener.onTimelineChanged(timeline, manifest, + Player.TIMELINE_CHANGE_REASON_PREPARED); waitForNotification.open(); } }