Skip to content

Commit

Permalink
Release all PlaybackStatsListener session when timeline becomes empty.
Browse files Browse the repository at this point in the history
Currently they are only released when the timeline becomes non-empty
again or the player is released.

Issue: #8778
PiperOrigin-RevId: 366041625
  • Loading branch information
marcbaechinger committed Apr 12, 2021
1 parent e6780bd commit 6d0a04d
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -293,18 +293,16 @@ public void onEvents(Player player, Events events) {
}

private void maybeAddSessions(Player player, Events events) {
if (player.getCurrentTimeline().isEmpty() && player.getPlaybackState() == Player.STATE_IDLE) {
// Player is completely idle. Don't add new sessions.
return;
}
boolean isCompletelyIdle =
player.getCurrentTimeline().isEmpty() && player.getPlaybackState() == Player.STATE_IDLE;
for (int i = 0; i < events.size(); i++) {
@EventFlags int event = events.get(i);
EventTime eventTime = events.getEventTime(event);
if (event == EVENT_TIMELINE_CHANGED) {
sessionManager.updateSessionsWithTimelineChange(eventTime);
} else if (event == EVENT_POSITION_DISCONTINUITY) {
} else if (!isCompletelyIdle && event == EVENT_POSITION_DISCONTINUITY) {
sessionManager.updateSessionsWithDiscontinuity(eventTime, discontinuityReason);
} else {
} else if (!isCompletelyIdle) {
sessionManager.updateSessions(eventTime);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.analytics;

import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilPendingCommandsAreFullyHandled;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -42,6 +43,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.shadows.ShadowLooper;

/** Unit test for {@link PlaybackStatsListener}. */
@RunWith(AndroidJUnit4.class)
Expand Down Expand Up @@ -151,6 +153,35 @@ public void finishedSession_callsCallback() {
verify(callback).onPlaybackStatsReady(any(), any());
}

@Test
public void playlistClear_callsAllPendingCallbacks() throws Exception {
PlaybackStatsListener.Callback callback = mock(PlaybackStatsListener.Callback.class);
PlaybackStatsListener playbackStatsListener =
new PlaybackStatsListener(/* keepHistory= */ true, callback);
player.addAnalyticsListener(playbackStatsListener);

MediaSource mediaSource = new FakeMediaSource(new FakeTimeline(/* windowCount= */ 1));
player.setMediaSources(ImmutableList.of(mediaSource, mediaSource));
player.prepare();
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
// Play close to the end of the first item to ensure the second session is already created, but
// the first one isn't finished yet.
TestPlayerRunHelper.playUntilPosition(
player, /* windowIndex= */ 0, /* positionMs= */ player.getDuration());
runUntilPendingCommandsAreFullyHandled(player);
player.clearMediaItems();
ShadowLooper.idleMainLooper();

ArgumentCaptor<AnalyticsListener.EventTime> eventTimeCaptor =
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
verify(callback, times(2)).onPlaybackStatsReady(eventTimeCaptor.capture(), any());
assertThat(
eventTimeCaptor.getAllValues().stream()
.map(eventTime -> eventTime.windowIndex)
.collect(Collectors.toList()))
.containsExactly(0, 1);
}

@Test
public void playerRelease_callsAllPendingCallbacks() throws Exception {
PlaybackStatsListener.Callback callback = mock(PlaybackStatsListener.Callback.class);
Expand Down

0 comments on commit 6d0a04d

Please sign in to comment.