Commit c027b4e7 by andrewlewis Committed by Oliver Woodman

Turn on nullness checker for playback stats

The nullness checker complains about Integers with @IntDef annotations
so replace pairs with custom pair types for the timed event records in
PlaybackStats.

PiperOrigin-RevId: 284731834
parent 70ba4b19
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
package com.google.android.exoplayer2.analytics; package com.google.android.exoplayer2.analytics;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Pair;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime; import com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime;
...@@ -28,11 +28,136 @@ import java.lang.annotation.RetentionPolicy; ...@@ -28,11 +28,136 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** Statistics about playbacks. */ /** Statistics about playbacks. */
public final class PlaybackStats { public final class PlaybackStats {
/** Stores a playback state with the event time at which it became active. */
public static final class EventTimeAndPlaybackState {
/** The event time at which the playback state became active. */
public final EventTime eventTime;
/** The playback state that became active. */
public final @PlaybackState int playbackState;
/**
* Creates a new timed playback state event.
*
* @param eventTime The event time at which the playback state became active.
* @param playbackState The playback state that became active.
*/
public EventTimeAndPlaybackState(EventTime eventTime, @PlaybackState int playbackState) {
this.eventTime = eventTime;
this.playbackState = playbackState;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EventTimeAndPlaybackState that = (EventTimeAndPlaybackState) o;
if (playbackState != that.playbackState) {
return false;
}
return eventTime.equals(that.eventTime);
}
@Override
public int hashCode() {
int result = eventTime.hashCode();
result = 31 * result + playbackState;
return result;
}
}
/**
* Stores a format with the event time at which it started being used, or {@code null} to indicate
* that no format was used.
*/
public static final class EventTimeAndFormat {
/** The event time associated with {@link #format}. */
public final EventTime eventTime;
/** The format that started being used, or {@code null} if no format was used. */
@Nullable public final Format format;
/**
* Creates a new timed format event.
*
* @param eventTime The event time associated with {@code format}.
* @param format The format that started being used, or {@code null} if no format was used.
*/
public EventTimeAndFormat(EventTime eventTime, @Nullable Format format) {
this.eventTime = eventTime;
this.format = format;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EventTimeAndFormat that = (EventTimeAndFormat) o;
if (!eventTime.equals(that.eventTime)) {
return false;
}
return format != null ? format.equals(that.format) : that.format == null;
}
@Override
public int hashCode() {
int result = eventTime.hashCode();
result = 31 * result + (format != null ? format.hashCode() : 0);
return result;
}
}
/** Stores an exception with the event time at which it occurred. */
public static final class EventTimeAndException {
/** The event time at which the exception occurred. */
public final EventTime eventTime;
/** The exception that was thrown. */
public final Exception exception;
/**
* Creates a new timed exception event.
*
* @param eventTime The event time at which the exception occurred.
* @param exception The exception that was thrown.
*/
public EventTimeAndException(EventTime eventTime, Exception exception) {
this.eventTime = eventTime;
this.exception = exception;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EventTimeAndException that = (EventTimeAndException) o;
if (!eventTime.equals(that.eventTime)) {
return false;
}
return exception.equals(that.exception);
}
@Override
public int hashCode() {
int result = eventTime.hashCode();
result = 31 * result + exception.hashCode();
return result;
}
}
/** /**
* State of a playback. One of {@link #PLAYBACK_STATE_NOT_STARTED}, {@link * State of a playback. One of {@link #PLAYBACK_STATE_NOT_STARTED}, {@link
* #PLAYBACK_STATE_JOINING_FOREGROUND}, {@link #PLAYBACK_STATE_JOINING_BACKGROUND}, {@link * #PLAYBACK_STATE_JOINING_FOREGROUND}, {@link #PLAYBACK_STATE_JOINING_BACKGROUND}, {@link
...@@ -258,10 +383,10 @@ public final class PlaybackStats { ...@@ -258,10 +383,10 @@ public final class PlaybackStats {
// Playback state stats. // Playback state stats.
/** /**
* The playback state history as ordered pairs of the {@link EventTime} at which a state became * The playback state history as {@link EventTimeAndPlaybackState EventTimeAndPlaybackStates}
* active and the {@link PlaybackState}. * ordered by {@code EventTime.realTimeMs}.
*/ */
public final List<Pair<EventTime, @PlaybackState Integer>> playbackStateHistory; public final List<EventTimeAndPlaybackState> playbackStateHistory;
/** /**
* The media time history as an ordered list of long[2] arrays with [0] being the realtime as * The media time history as an ordered list of long[2] arrays with [0] being the realtime as
* returned by {@code SystemClock.elapsedRealtime()} and [1] being the media time at this * returned by {@code SystemClock.elapsedRealtime()} and [1] being the media time at this
...@@ -319,15 +444,15 @@ public final class PlaybackStats { ...@@ -319,15 +444,15 @@ public final class PlaybackStats {
// Format stats. // Format stats.
/** /**
* The video format history as ordered pairs of the {@link EventTime} at which a format started * The video format history as {@link EventTimeAndFormat EventTimeAndFormats} ordered by {@code
* being used and the {@link Format}. The {@link Format} may be null if no video format was used. * EventTime.realTimeMs}. The {@link Format} may be null if no video format was used.
*/ */
public final List<Pair<EventTime, @NullableType Format>> videoFormatHistory; public final List<EventTimeAndFormat> videoFormatHistory;
/** /**
* The audio format history as ordered pairs of the {@link EventTime} at which a format started * The audio format history as {@link EventTimeAndFormat EventTimeAndFormats} ordered by {@code
* being used and the {@link Format}. The {@link Format} may be null if no audio format was used. * EventTime.realTimeMs}. The {@link Format} may be null if no audio format was used.
*/ */
public final List<Pair<EventTime, @NullableType Format>> audioFormatHistory; public final List<EventTimeAndFormat> audioFormatHistory;
/** The total media time for which video format height data is available, in milliseconds. */ /** The total media time for which video format height data is available, in milliseconds. */
public final long totalVideoFormatHeightTimeMs; public final long totalVideoFormatHeightTimeMs;
/** /**
...@@ -400,23 +525,23 @@ public final class PlaybackStats { ...@@ -400,23 +525,23 @@ public final class PlaybackStats {
*/ */
public final int nonFatalErrorCount; public final int nonFatalErrorCount;
/** /**
* The history of fatal errors as ordered pairs of the {@link EventTime} at which an error * The history of fatal errors as {@link EventTimeAndException EventTimeAndExceptions} ordered by
* occurred and the error. Errors are fatal if playback stopped due to this error. * {@code EventTime.realTimeMs}. Errors are fatal if playback stopped due to this error.
*/ */
public final List<Pair<EventTime, Exception>> fatalErrorHistory; public final List<EventTimeAndException> fatalErrorHistory;
/** /**
* The history of non-fatal errors as ordered pairs of the {@link EventTime} at which an error * The history of non-fatal errors as {@link EventTimeAndException EventTimeAndExceptions} ordered
* occurred and the error. Error are non-fatal if playback can recover from the error without * by {@code EventTime.realTimeMs}. Errors are non-fatal if playback can recover from the error
* stopping. * without stopping.
*/ */
public final List<Pair<EventTime, Exception>> nonFatalErrorHistory; public final List<EventTimeAndException> nonFatalErrorHistory;
private final long[] playbackStateDurationsMs; private final long[] playbackStateDurationsMs;
/* package */ PlaybackStats( /* package */ PlaybackStats(
int playbackCount, int playbackCount,
long[] playbackStateDurationsMs, long[] playbackStateDurationsMs,
List<Pair<EventTime, @PlaybackState Integer>> playbackStateHistory, List<EventTimeAndPlaybackState> playbackStateHistory,
List<long[]> mediaTimeHistory, List<long[]> mediaTimeHistory,
long firstReportedTimeMs, long firstReportedTimeMs,
int foregroundPlaybackCount, int foregroundPlaybackCount,
...@@ -431,8 +556,8 @@ public final class PlaybackStats { ...@@ -431,8 +556,8 @@ public final class PlaybackStats {
int totalRebufferCount, int totalRebufferCount,
long maxRebufferTimeMs, long maxRebufferTimeMs,
int adPlaybackCount, int adPlaybackCount,
List<Pair<EventTime, @NullableType Format>> videoFormatHistory, List<EventTimeAndFormat> videoFormatHistory,
List<Pair<EventTime, @NullableType Format>> audioFormatHistory, List<EventTimeAndFormat> audioFormatHistory,
long totalVideoFormatHeightTimeMs, long totalVideoFormatHeightTimeMs,
long totalVideoFormatHeightTimeProduct, long totalVideoFormatHeightTimeProduct,
long totalVideoFormatBitrateTimeMs, long totalVideoFormatBitrateTimeMs,
...@@ -452,8 +577,8 @@ public final class PlaybackStats { ...@@ -452,8 +577,8 @@ public final class PlaybackStats {
int fatalErrorPlaybackCount, int fatalErrorPlaybackCount,
int fatalErrorCount, int fatalErrorCount,
int nonFatalErrorCount, int nonFatalErrorCount,
List<Pair<EventTime, Exception>> fatalErrorHistory, List<EventTimeAndException> fatalErrorHistory,
List<Pair<EventTime, Exception>> nonFatalErrorHistory) { List<EventTimeAndException> nonFatalErrorHistory) {
this.playbackCount = playbackCount; this.playbackCount = playbackCount;
this.playbackStateDurationsMs = playbackStateDurationsMs; this.playbackStateDurationsMs = playbackStateDurationsMs;
this.playbackStateHistory = Collections.unmodifiableList(playbackStateHistory); this.playbackStateHistory = Collections.unmodifiableList(playbackStateHistory);
...@@ -515,11 +640,11 @@ public final class PlaybackStats { ...@@ -515,11 +640,11 @@ public final class PlaybackStats {
*/ */
public @PlaybackState int getPlaybackStateAtTime(long realtimeMs) { public @PlaybackState int getPlaybackStateAtTime(long realtimeMs) {
@PlaybackState int state = PLAYBACK_STATE_NOT_STARTED; @PlaybackState int state = PLAYBACK_STATE_NOT_STARTED;
for (Pair<EventTime, @PlaybackState Integer> timeAndState : playbackStateHistory) { for (EventTimeAndPlaybackState timeAndState : playbackStateHistory) {
if (timeAndState.first.realtimeMs > realtimeMs) { if (timeAndState.eventTime.realtimeMs > realtimeMs) {
break; break;
} }
state = timeAndState.second; state = timeAndState.playbackState;
} }
return state; return state;
} }
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
package com.google.android.exoplayer2.analytics; package com.google.android.exoplayer2.analytics;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Pair;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlaybackException;
...@@ -25,6 +24,9 @@ import com.google.android.exoplayer2.PlaybackParameters; ...@@ -25,6 +24,9 @@ import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.Timeline; import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.Timeline.Period; import com.google.android.exoplayer2.Timeline.Period;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndException;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndFormat;
import com.google.android.exoplayer2.analytics.PlaybackStats.EventTimeAndPlaybackState;
import com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackState; import com.google.android.exoplayer2.analytics.PlaybackStats.PlaybackState;
import com.google.android.exoplayer2.source.LoadEventInfo; import com.google.android.exoplayer2.source.LoadEventInfo;
import com.google.android.exoplayer2.source.MediaLoadData; import com.google.android.exoplayer2.source.MediaLoadData;
...@@ -42,7 +44,6 @@ import java.util.Collections; ...@@ -42,7 +44,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.checkerframework.checker.nullness.compatqual.NullableType;
/** /**
* {@link AnalyticsListener} to gather {@link PlaybackStats} from the player. * {@link AnalyticsListener} to gather {@link PlaybackStats} from the player.
...@@ -433,12 +434,12 @@ public final class PlaybackStatsListener ...@@ -433,12 +434,12 @@ public final class PlaybackStatsListener
// Final stats. // Final stats.
private final boolean keepHistory; private final boolean keepHistory;
private final long[] playbackStateDurationsMs; private final long[] playbackStateDurationsMs;
private final List<Pair<EventTime, @PlaybackState Integer>> playbackStateHistory; private final List<EventTimeAndPlaybackState> playbackStateHistory;
private final List<long[]> mediaTimeHistory; private final List<long[]> mediaTimeHistory;
private final List<Pair<EventTime, @NullableType Format>> videoFormatHistory; private final List<EventTimeAndFormat> videoFormatHistory;
private final List<Pair<EventTime, @NullableType Format>> audioFormatHistory; private final List<EventTimeAndFormat> audioFormatHistory;
private final List<Pair<EventTime, Exception>> fatalErrorHistory; private final List<EventTimeAndException> fatalErrorHistory;
private final List<Pair<EventTime, Exception>> nonFatalErrorHistory; private final List<EventTimeAndException> nonFatalErrorHistory;
private final boolean isAd; private final boolean isAd;
private long firstReportedTimeMs; private long firstReportedTimeMs;
...@@ -589,7 +590,7 @@ public final class PlaybackStatsListener ...@@ -589,7 +590,7 @@ public final class PlaybackStatsListener
public void onFatalError(EventTime eventTime, Exception error) { public void onFatalError(EventTime eventTime, Exception error) {
fatalErrorCount++; fatalErrorCount++;
if (keepHistory) { if (keepHistory) {
fatalErrorHistory.add(Pair.create(eventTime, error)); fatalErrorHistory.add(new EventTimeAndException(eventTime, error));
} }
hasFatalError = true; hasFatalError = true;
isInterruptedByAd = false; isInterruptedByAd = false;
...@@ -743,7 +744,7 @@ public final class PlaybackStatsListener ...@@ -743,7 +744,7 @@ public final class PlaybackStatsListener
public void onNonFatalError(EventTime eventTime, Exception error) { public void onNonFatalError(EventTime eventTime, Exception error) {
nonFatalErrorCount++; nonFatalErrorCount++;
if (keepHistory) { if (keepHistory) {
nonFatalErrorHistory.add(Pair.create(eventTime, error)); nonFatalErrorHistory.add(new EventTimeAndException(eventTime, error));
} }
} }
...@@ -776,9 +777,9 @@ public final class PlaybackStatsListener ...@@ -776,9 +777,9 @@ public final class PlaybackStatsListener
: playbackStateDurationsMs[PlaybackStats.PLAYBACK_STATE_JOINING_FOREGROUND]; : playbackStateDurationsMs[PlaybackStats.PLAYBACK_STATE_JOINING_FOREGROUND];
boolean hasBackgroundJoin = boolean hasBackgroundJoin =
playbackStateDurationsMs[PlaybackStats.PLAYBACK_STATE_JOINING_BACKGROUND] > 0; playbackStateDurationsMs[PlaybackStats.PLAYBACK_STATE_JOINING_BACKGROUND] > 0;
List<Pair<EventTime, @NullableType Format>> videoHistory = List<EventTimeAndFormat> videoHistory =
isFinal ? videoFormatHistory : new ArrayList<>(videoFormatHistory); isFinal ? videoFormatHistory : new ArrayList<>(videoFormatHistory);
List<Pair<EventTime, @NullableType Format>> audioHistory = List<EventTimeAndFormat> audioHistory =
isFinal ? audioFormatHistory : new ArrayList<>(audioFormatHistory); isFinal ? audioFormatHistory : new ArrayList<>(audioFormatHistory);
return new PlaybackStats( return new PlaybackStats(
/* playbackCount= */ 1, /* playbackCount= */ 1,
...@@ -864,7 +865,7 @@ public final class PlaybackStatsListener ...@@ -864,7 +865,7 @@ public final class PlaybackStatsListener
currentPlaybackState = newPlaybackState; currentPlaybackState = newPlaybackState;
currentPlaybackStateStartTimeMs = eventTime.realtimeMs; currentPlaybackStateStartTimeMs = eventTime.realtimeMs;
if (keepHistory) { if (keepHistory) {
playbackStateHistory.add(Pair.create(eventTime, currentPlaybackState)); playbackStateHistory.add(new EventTimeAndPlaybackState(eventTime, currentPlaybackState));
} }
} }
...@@ -973,7 +974,7 @@ public final class PlaybackStatsListener ...@@ -973,7 +974,7 @@ public final class PlaybackStatsListener
} }
currentVideoFormat = newFormat; currentVideoFormat = newFormat;
if (keepHistory) { if (keepHistory) {
videoFormatHistory.add(Pair.create(eventTime, currentVideoFormat)); videoFormatHistory.add(new EventTimeAndFormat(eventTime, currentVideoFormat));
} }
} }
...@@ -989,7 +990,7 @@ public final class PlaybackStatsListener ...@@ -989,7 +990,7 @@ public final class PlaybackStatsListener
} }
currentAudioFormat = newFormat; currentAudioFormat = newFormat;
if (keepHistory) { if (keepHistory) {
audioFormatHistory.add(Pair.create(eventTime, currentAudioFormat)); audioFormatHistory.add(new EventTimeAndFormat(eventTime, currentAudioFormat));
} }
} }
......
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