mirror of
https://github.com/samsonjs/media.git
synced 2026-03-29 10:05:48 +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;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Pair;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.Format;
|
||||
import com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime;
|
||||
|
|
@ -28,11 +28,136 @@ import java.lang.annotation.RetentionPolicy;
|
|||
import java.lang.annotation.Target;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
|
||||
/** Statistics about playbacks. */
|
||||
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
|
||||
* #PLAYBACK_STATE_JOINING_FOREGROUND}, {@link #PLAYBACK_STATE_JOINING_BACKGROUND}, {@link
|
||||
|
|
@ -258,10 +383,10 @@ public final class PlaybackStats {
|
|||
// Playback state stats.
|
||||
|
||||
/**
|
||||
* The playback state history as ordered pairs of the {@link EventTime} at which a state became
|
||||
* active and the {@link PlaybackState}.
|
||||
* The playback state history as {@link EventTimeAndPlaybackState EventTimeAndPlaybackStates}
|
||||
* 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
|
||||
* returned by {@code SystemClock.elapsedRealtime()} and [1] being the media time at this
|
||||
|
|
@ -319,15 +444,15 @@ public final class PlaybackStats {
|
|||
// Format stats.
|
||||
|
||||
/**
|
||||
* The video format history as ordered pairs of the {@link EventTime} at which a format started
|
||||
* being used and the {@link Format}. The {@link Format} may be null if no video format was used.
|
||||
* The video format history as {@link EventTimeAndFormat EventTimeAndFormats} ordered by {@code
|
||||
* 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
|
||||
* being used and the {@link Format}. The {@link Format} may be null if no audio format was used.
|
||||
* The audio format history as {@link EventTimeAndFormat EventTimeAndFormats} ordered by {@code
|
||||
* 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. */
|
||||
public final long totalVideoFormatHeightTimeMs;
|
||||
/**
|
||||
|
|
@ -400,23 +525,23 @@ public final class PlaybackStats {
|
|||
*/
|
||||
public final int nonFatalErrorCount;
|
||||
/**
|
||||
* The history of fatal errors as ordered pairs of the {@link EventTime} at which an error
|
||||
* occurred and the error. Errors are fatal if playback stopped due to this error.
|
||||
* The history of fatal errors as {@link EventTimeAndException EventTimeAndExceptions} ordered by
|
||||
* {@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
|
||||
* occurred and the error. Error are non-fatal if playback can recover from the error without
|
||||
* stopping.
|
||||
* The history of non-fatal errors as {@link EventTimeAndException EventTimeAndExceptions} ordered
|
||||
* by {@code EventTime.realTimeMs}. Errors are non-fatal if playback can recover from the error
|
||||
* without stopping.
|
||||
*/
|
||||
public final List<Pair<EventTime, Exception>> nonFatalErrorHistory;
|
||||
public final List<EventTimeAndException> nonFatalErrorHistory;
|
||||
|
||||
private final long[] playbackStateDurationsMs;
|
||||
|
||||
/* package */ PlaybackStats(
|
||||
int playbackCount,
|
||||
long[] playbackStateDurationsMs,
|
||||
List<Pair<EventTime, @PlaybackState Integer>> playbackStateHistory,
|
||||
List<EventTimeAndPlaybackState> playbackStateHistory,
|
||||
List<long[]> mediaTimeHistory,
|
||||
long firstReportedTimeMs,
|
||||
int foregroundPlaybackCount,
|
||||
|
|
@ -431,8 +556,8 @@ public final class PlaybackStats {
|
|||
int totalRebufferCount,
|
||||
long maxRebufferTimeMs,
|
||||
int adPlaybackCount,
|
||||
List<Pair<EventTime, @NullableType Format>> videoFormatHistory,
|
||||
List<Pair<EventTime, @NullableType Format>> audioFormatHistory,
|
||||
List<EventTimeAndFormat> videoFormatHistory,
|
||||
List<EventTimeAndFormat> audioFormatHistory,
|
||||
long totalVideoFormatHeightTimeMs,
|
||||
long totalVideoFormatHeightTimeProduct,
|
||||
long totalVideoFormatBitrateTimeMs,
|
||||
|
|
@ -452,8 +577,8 @@ public final class PlaybackStats {
|
|||
int fatalErrorPlaybackCount,
|
||||
int fatalErrorCount,
|
||||
int nonFatalErrorCount,
|
||||
List<Pair<EventTime, Exception>> fatalErrorHistory,
|
||||
List<Pair<EventTime, Exception>> nonFatalErrorHistory) {
|
||||
List<EventTimeAndException> fatalErrorHistory,
|
||||
List<EventTimeAndException> nonFatalErrorHistory) {
|
||||
this.playbackCount = playbackCount;
|
||||
this.playbackStateDurationsMs = playbackStateDurationsMs;
|
||||
this.playbackStateHistory = Collections.unmodifiableList(playbackStateHistory);
|
||||
|
|
@ -515,11 +640,11 @@ public final class PlaybackStats {
|
|||
*/
|
||||
public @PlaybackState int getPlaybackStateAtTime(long realtimeMs) {
|
||||
@PlaybackState int state = PLAYBACK_STATE_NOT_STARTED;
|
||||
for (Pair<EventTime, @PlaybackState Integer> timeAndState : playbackStateHistory) {
|
||||
if (timeAndState.first.realtimeMs > realtimeMs) {
|
||||
for (EventTimeAndPlaybackState timeAndState : playbackStateHistory) {
|
||||
if (timeAndState.eventTime.realtimeMs > realtimeMs) {
|
||||
break;
|
||||
}
|
||||
state = timeAndState.second;
|
||||
state = timeAndState.playbackState;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
package com.google.android.exoplayer2.analytics;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.util.Pair;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.exoplayer2.C;
|
||||
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.Timeline;
|
||||
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.source.LoadEventInfo;
|
||||
import com.google.android.exoplayer2.source.MediaLoadData;
|
||||
|
|
@ -42,7 +44,6 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
||||
|
||||
/**
|
||||
* {@link AnalyticsListener} to gather {@link PlaybackStats} from the player.
|
||||
|
|
@ -433,12 +434,12 @@ public final class PlaybackStatsListener
|
|||
// Final stats.
|
||||
private final boolean keepHistory;
|
||||
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<Pair<EventTime, @NullableType Format>> videoFormatHistory;
|
||||
private final List<Pair<EventTime, @NullableType Format>> audioFormatHistory;
|
||||
private final List<Pair<EventTime, Exception>> fatalErrorHistory;
|
||||
private final List<Pair<EventTime, Exception>> nonFatalErrorHistory;
|
||||
private final List<EventTimeAndFormat> videoFormatHistory;
|
||||
private final List<EventTimeAndFormat> audioFormatHistory;
|
||||
private final List<EventTimeAndException> fatalErrorHistory;
|
||||
private final List<EventTimeAndException> nonFatalErrorHistory;
|
||||
private final boolean isAd;
|
||||
|
||||
private long firstReportedTimeMs;
|
||||
|
|
@ -589,7 +590,7 @@ public final class PlaybackStatsListener
|
|||
public void onFatalError(EventTime eventTime, Exception error) {
|
||||
fatalErrorCount++;
|
||||
if (keepHistory) {
|
||||
fatalErrorHistory.add(Pair.create(eventTime, error));
|
||||
fatalErrorHistory.add(new EventTimeAndException(eventTime, error));
|
||||
}
|
||||
hasFatalError = true;
|
||||
isInterruptedByAd = false;
|
||||
|
|
@ -743,7 +744,7 @@ public final class PlaybackStatsListener
|
|||
public void onNonFatalError(EventTime eventTime, Exception error) {
|
||||
nonFatalErrorCount++;
|
||||
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];
|
||||
boolean hasBackgroundJoin =
|
||||
playbackStateDurationsMs[PlaybackStats.PLAYBACK_STATE_JOINING_BACKGROUND] > 0;
|
||||
List<Pair<EventTime, @NullableType Format>> videoHistory =
|
||||
List<EventTimeAndFormat> videoHistory =
|
||||
isFinal ? videoFormatHistory : new ArrayList<>(videoFormatHistory);
|
||||
List<Pair<EventTime, @NullableType Format>> audioHistory =
|
||||
List<EventTimeAndFormat> audioHistory =
|
||||
isFinal ? audioFormatHistory : new ArrayList<>(audioFormatHistory);
|
||||
return new PlaybackStats(
|
||||
/* playbackCount= */ 1,
|
||||
|
|
@ -864,7 +865,7 @@ public final class PlaybackStatsListener
|
|||
currentPlaybackState = newPlaybackState;
|
||||
currentPlaybackStateStartTimeMs = eventTime.realtimeMs;
|
||||
if (keepHistory) {
|
||||
playbackStateHistory.add(Pair.create(eventTime, currentPlaybackState));
|
||||
playbackStateHistory.add(new EventTimeAndPlaybackState(eventTime, currentPlaybackState));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -973,7 +974,7 @@ public final class PlaybackStatsListener
|
|||
}
|
||||
currentVideoFormat = newFormat;
|
||||
if (keepHistory) {
|
||||
videoFormatHistory.add(Pair.create(eventTime, currentVideoFormat));
|
||||
videoFormatHistory.add(new EventTimeAndFormat(eventTime, currentVideoFormat));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -989,7 +990,7 @@ public final class PlaybackStatsListener
|
|||
}
|
||||
currentAudioFormat = newFormat;
|
||||
if (keepHistory) {
|
||||
audioFormatHistory.add(Pair.create(eventTime, currentAudioFormat));
|
||||
audioFormatHistory.add(new EventTimeAndFormat(eventTime, currentAudioFormat));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue