diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 9a45664a14..b22fd1a315 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -25,6 +25,8 @@ * UI: Add an option to set whether to use the orientation sensor for rotation in spherical playbacks ([#6761](https://github.com/google/ExoPlayer/issues/6761)). +* Analytics: Fix `PlaybackStatsListener` behavior when not keeping history + ([#7160](https://github.com/google/ExoPlayer/issues/7160)). * FFmpeg extension: Add support for x86_64. * Opus extension: Fix parsing of negative gain values ([#7046](https://github.com/google/ExoPlayer/issues/7046)). diff --git a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java index 3430bfc1dd..a9fd9d8641 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/analytics/PlaybackStatsListener.java @@ -50,7 +50,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; *

For accurate measurements, the listener should be added to the player before loading media, * i.e., {@link Player#getPlaybackState()} should be {@link Player#STATE_IDLE}. * - *

Playback stats are gathered separately for all playback session, i.e. each window in the + *

Playback stats are gathered separately for each playback session, i.e. each window in the * {@link Timeline} and each single ad. */ public final class PlaybackStatsListener @@ -931,6 +931,9 @@ public final class PlaybackStatsListener } private void maybeUpdateMediaTimeHistory(long realtimeMs, long mediaTimeMs) { + if (!keepHistory) { + return; + } if (currentPlaybackState != PlaybackStats.PLAYBACK_STATE_PLAYING) { if (mediaTimeMs == C.TIME_UNSET) { return; diff --git a/library/core/src/test/java/com/google/android/exoplayer2/analytics/PlaybackStatsListenerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/analytics/PlaybackStatsListenerTest.java new file mode 100644 index 0000000000..10122d36ec --- /dev/null +++ b/library/core/src/test/java/com/google/android/exoplayer2/analytics/PlaybackStatsListenerTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.google.android.exoplayer2.analytics; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.annotation.Nullable; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.Timeline; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** Unit test for {@link PlaybackStatsListener}. */ +@RunWith(AndroidJUnit4.class) +public final class PlaybackStatsListenerTest { + + private static final AnalyticsListener.EventTime TEST_EVENT_TIME = + new AnalyticsListener.EventTime( + /* realtimeMs= */ 500, + Timeline.EMPTY, + /* windowIndex= */ 0, + /* mediaPeriodId= */ null, + /* eventPlaybackPositionMs= */ 0, + /* currentPlaybackPositionMs= */ 0, + /* totalBufferedDurationMs= */ 0); + + @Test + public void playback_withKeepHistory_updatesStats() { + PlaybackStatsListener playbackStatsListener = + new PlaybackStatsListener(/* keepHistory= */ true, /* callback= */ null); + + playbackStatsListener.onPlayerStateChanged( + TEST_EVENT_TIME, /* playWhenReady= */ true, Player.STATE_BUFFERING); + playbackStatsListener.onPlayerStateChanged( + TEST_EVENT_TIME, /* playWhenReady= */ true, Player.STATE_READY); + playbackStatsListener.onPlayerStateChanged( + TEST_EVENT_TIME, /* playWhenReady= */ true, Player.STATE_ENDED); + + @Nullable PlaybackStats playbackStats = playbackStatsListener.getPlaybackStats(); + assertThat(playbackStats).isNotNull(); + assertThat(playbackStats.endedCount).isEqualTo(1); + } + + @Test + public void playback_withoutKeepHistory_updatesStats() { + PlaybackStatsListener playbackStatsListener = + new PlaybackStatsListener(/* keepHistory= */ false, /* callback= */ null); + + playbackStatsListener.onPlayerStateChanged( + TEST_EVENT_TIME, /* playWhenReady= */ true, Player.STATE_BUFFERING); + playbackStatsListener.onPlayerStateChanged( + TEST_EVENT_TIME, /* playWhenReady= */ true, Player.STATE_READY); + playbackStatsListener.onPlayerStateChanged( + TEST_EVENT_TIME, /* playWhenReady= */ true, Player.STATE_ENDED); + + @Nullable PlaybackStats playbackStats = playbackStatsListener.getPlaybackStats(); + assertThat(playbackStats).isNotNull(); + assertThat(playbackStats.endedCount).isEqualTo(1); + } +}