Commit 7c60e67f by tonihei Committed by Ian Baker

End finished sessions on timeline updates.

We currently only end sessions on Timeline updates if the associated media
is no longer in the playlist. But we should also end all sessions that are
finished as a result of the timeline update (similar to how this is done for
discontinuities). This issue was introduced by https://github.com/google/ExoPlayer/commit/394ab7bcfd53bc8ffb8d2e37a5aeb71fef04d13c

PiperOrigin-RevId: 423075855
parent 6fd4401e
......@@ -177,7 +177,8 @@ public final class DefaultPlaybackSessionManager implements PlaybackSessionManag
Iterator<SessionDescriptor> iterator = sessions.values().iterator();
while (iterator.hasNext()) {
SessionDescriptor session = iterator.next();
if (!session.tryResolvingToNewTimeline(previousTimeline, currentTimeline)) {
if (!session.tryResolvingToNewTimeline(previousTimeline, currentTimeline)
|| session.isFinishedAtEventTime(eventTime)) {
iterator.remove();
if (session.isCreated) {
if (session.sessionId.equals(currentSessionId)) {
......
......@@ -744,6 +744,128 @@ public final class DefaultPlaybackSessionManagerTest {
}
@Test
public void timelineUpdate_toNewMediaWithWindowIndexOnly_finishesOtherSessions() {
Timeline firstTimeline =
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 1000),
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 2000),
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 3000));
EventTime eventTimeFirstTimelineWithPeriodId =
createEventTime(
firstTimeline,
/* windowIndex= */ 0,
new MediaPeriodId(
firstTimeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0));
EventTime eventTimeFirstTimelineWindowOnly1 =
createEventTime(firstTimeline, /* windowIndex= */ 1, /* mediaPeriodId= */ null);
EventTime eventTimeFirstTimelineWindowOnly2 =
createEventTime(firstTimeline, /* windowIndex= */ 2, /* mediaPeriodId= */ null);
Timeline secondTimeline =
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 2000),
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 4000));
EventTime eventTimeSecondTimeline =
createEventTime(secondTimeline, /* windowIndex= */ 0, /* mediaPeriodId= */ null);
sessionManager.updateSessionsWithTimelineChange(eventTimeFirstTimelineWithPeriodId);
sessionManager.updateSessions(eventTimeFirstTimelineWindowOnly1);
sessionManager.updateSessions(eventTimeFirstTimelineWindowOnly2);
sessionManager.updateSessionsWithTimelineChange(eventTimeSecondTimeline);
InOrder inOrder = inOrder(mockListener);
ArgumentCaptor<String> firstId = ArgumentCaptor.forClass(String.class);
inOrder
.verify(mockListener)
.onSessionCreated(eq(eventTimeFirstTimelineWithPeriodId), firstId.capture());
inOrder
.verify(mockListener)
.onSessionActive(eventTimeFirstTimelineWithPeriodId, firstId.getValue());
ArgumentCaptor<String> secondId = ArgumentCaptor.forClass(String.class);
inOrder
.verify(mockListener)
.onSessionCreated(eq(eventTimeFirstTimelineWindowOnly1), secondId.capture());
ArgumentCaptor<String> thirdId = ArgumentCaptor.forClass(String.class);
inOrder
.verify(mockListener)
.onSessionCreated(eq(eventTimeFirstTimelineWindowOnly2), thirdId.capture());
inOrder
.verify(mockListener)
.onSessionFinished(
eventTimeSecondTimeline,
firstId.getValue(),
/* automaticTransitionToNextPlayback= */ false);
inOrder
.verify(mockListener)
.onSessionFinished(
eventTimeSecondTimeline,
thirdId.getValue(),
/* automaticTransitionToNextPlayback= */ false);
inOrder.verify(mockListener).onSessionActive(eventTimeSecondTimeline, secondId.getValue());
inOrder.verifyNoMoreInteractions();
}
@Test
public void timelineUpdate_toNewMediaWithMediaPeriodId_finishesOtherSessions() {
Timeline firstTimeline =
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 1000),
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 2000),
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 3000));
EventTime eventTimeFirstTimeline1 =
createEventTime(
firstTimeline,
/* windowIndex= */ 0,
new MediaPeriodId(
firstTimeline.getUidOfPeriod(/* periodIndex= */ 0), /* windowSequenceNumber= */ 0));
EventTime eventTimeFirstTimeline2 =
createEventTime(
firstTimeline,
/* windowIndex= */ 1,
new MediaPeriodId(
firstTimeline.getUidOfPeriod(/* periodIndex= */ 1), /* windowSequenceNumber= */ 1));
EventTime eventTimeFirstTimeline3 =
createEventTime(
firstTimeline,
/* windowIndex= */ 2,
new MediaPeriodId(
firstTimeline.getUidOfPeriod(/* periodIndex= */ 2), /* windowSequenceNumber= */ 2));
Timeline secondTimeline =
new FakeTimeline(
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 2000),
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 1000),
new TimelineWindowDefinition(/* periodCount= */ 1, /* id= */ 3000));
EventTime eventTimeSecondTimeline =
createEventTime(
secondTimeline,
/* windowIndex= */ 0,
new MediaPeriodId(
secondTimeline.getUidOfPeriod(/* periodIndex= */ 0),
/* windowSequenceNumber= */ 1));
sessionManager.updateSessionsWithTimelineChange(eventTimeFirstTimeline1);
sessionManager.updateSessions(eventTimeFirstTimeline2);
sessionManager.updateSessions(eventTimeFirstTimeline3);
sessionManager.updateSessionsWithTimelineChange(eventTimeSecondTimeline);
InOrder inOrder = inOrder(mockListener);
ArgumentCaptor<String> firstId = ArgumentCaptor.forClass(String.class);
inOrder.verify(mockListener).onSessionCreated(eq(eventTimeFirstTimeline1), firstId.capture());
inOrder.verify(mockListener).onSessionActive(eventTimeFirstTimeline1, firstId.getValue());
ArgumentCaptor<String> secondId = ArgumentCaptor.forClass(String.class);
inOrder.verify(mockListener).onSessionCreated(eq(eventTimeFirstTimeline2), secondId.capture());
ArgumentCaptor<String> thirdId = ArgumentCaptor.forClass(String.class);
inOrder.verify(mockListener).onSessionCreated(eq(eventTimeFirstTimeline3), thirdId.capture());
inOrder
.verify(mockListener)
.onSessionFinished(
eventTimeSecondTimeline,
firstId.getValue(),
/* automaticTransitionToNextPlayback= */ false);
inOrder.verify(mockListener).onSessionActive(eventTimeSecondTimeline, secondId.getValue());
inOrder.verifyNoMoreInteractions();
}
@Test
public void positionDiscontinuity_withinWindow_doesNotFinishSession() {
Timeline timeline =
new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */ 2, /* id= */ 100));
......
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