mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
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
This commit is contained in:
parent
70ba4b197c
commit
c027b4e71a
2 changed files with 166 additions and 40 deletions
|
|
@ -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;
|
||||||
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 {
|
||||||
// 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 {
|
||||||
// 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 {
|
||||||
*/
|
*/
|
||||||
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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
*/
|
*/
|
||||||
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 @@
|
||||||
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;
|
||||||
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;
|
||||||
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
|
||||||
// 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
|
||||||
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
|
||||||
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
|
||||||
: 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
|
||||||
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
|
||||||
}
|
}
|
||||||
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
|
||||||
}
|
}
|
||||||
currentAudioFormat = newFormat;
|
currentAudioFormat = newFormat;
|
||||||
if (keepHistory) {
|
if (keepHistory) {
|
||||||
audioFormatHistory.add(Pair.create(eventTime, currentAudioFormat));
|
audioFormatHistory.add(new EventTimeAndFormat(eventTime, currentAudioFormat));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue