Add EventTimes to AnalyticsListener.onEvents
The EventTime wasn't part of the onEvents callbacks so far because the individual events may have different event times (e.g. if they relate to different media periods). By adding a query method to obtain the EventTime by event type, we can solve this issue. #exofixit PiperOrigin-RevId: 343818819
This commit is contained in:
parent
7d3399764e
commit
e5e903eb8a
@ -18,6 +18,7 @@ package com.google.android.exoplayer2.analytics;
|
|||||||
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||||
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
@ -80,6 +81,7 @@ public class AnalyticsCollector
|
|||||||
private final Period period;
|
private final Period period;
|
||||||
private final Window window;
|
private final Window window;
|
||||||
private final MediaPeriodQueueTracker mediaPeriodQueueTracker;
|
private final MediaPeriodQueueTracker mediaPeriodQueueTracker;
|
||||||
|
private final SparseArray<EventTime> eventTimes;
|
||||||
|
|
||||||
private ListenerSet<AnalyticsListener, AnalyticsListener.Events> listeners;
|
private ListenerSet<AnalyticsListener, AnalyticsListener.Events> listeners;
|
||||||
private @MonotonicNonNull Player player;
|
private @MonotonicNonNull Player player;
|
||||||
@ -100,6 +102,7 @@ public class AnalyticsCollector
|
|||||||
period = new Period();
|
period = new Period();
|
||||||
window = new Window();
|
window = new Window();
|
||||||
mediaPeriodQueueTracker = new MediaPeriodQueueTracker(period);
|
mediaPeriodQueueTracker = new MediaPeriodQueueTracker(period);
|
||||||
|
eventTimes = new SparseArray<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,7 +136,12 @@ public class AnalyticsCollector
|
|||||||
this.player == null || mediaPeriodQueueTracker.mediaPeriodQueue.isEmpty());
|
this.player == null || mediaPeriodQueueTracker.mediaPeriodQueue.isEmpty());
|
||||||
this.player = checkNotNull(player);
|
this.player = checkNotNull(player);
|
||||||
listeners =
|
listeners =
|
||||||
listeners.copy(looper, (listener, eventFlags) -> listener.onEvents(player, eventFlags));
|
listeners.copy(
|
||||||
|
looper,
|
||||||
|
(listener, events) -> {
|
||||||
|
events.setEventTimes(eventTimes);
|
||||||
|
listener.onEvents(player, events);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,8 +168,8 @@ public class AnalyticsCollector
|
|||||||
if (!isSeeking) {
|
if (!isSeeking) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
isSeeking = true;
|
isSeeking = true;
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onSeekStarted(eventTime));
|
eventTime, /* eventFlag= */ C.INDEX_UNSET, listener -> listener.onSeekStarted(eventTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,8 +183,10 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onMetadata(Metadata metadata) {
|
public final void onMetadata(Metadata metadata) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
AnalyticsListener.EVENT_METADATA, listener -> listener.onMetadata(eventTime, metadata));
|
eventTime,
|
||||||
|
AnalyticsListener.EVENT_METADATA,
|
||||||
|
listener -> listener.onMetadata(eventTime, metadata));
|
||||||
}
|
}
|
||||||
|
|
||||||
// AudioRendererEventListener implementation.
|
// AudioRendererEventListener implementation.
|
||||||
@ -185,7 +195,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onAudioEnabled(DecoderCounters counters) {
|
public final void onAudioEnabled(DecoderCounters counters) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_ENABLED,
|
AnalyticsListener.EVENT_AUDIO_ENABLED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onAudioEnabled(eventTime, counters);
|
listener.onAudioEnabled(eventTime, counters);
|
||||||
@ -198,7 +209,8 @@ public class AnalyticsCollector
|
|||||||
public final void onAudioDecoderInitialized(
|
public final void onAudioDecoderInitialized(
|
||||||
String decoderName, long initializedTimestampMs, long initializationDurationMs) {
|
String decoderName, long initializedTimestampMs, long initializationDurationMs) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_DECODER_INITIALIZED,
|
AnalyticsListener.EVENT_AUDIO_DECODER_INITIALIZED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onAudioDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
listener.onAudioDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
||||||
@ -212,7 +224,8 @@ public class AnalyticsCollector
|
|||||||
public final void onAudioInputFormatChanged(
|
public final void onAudioInputFormatChanged(
|
||||||
Format format, @Nullable DecoderReuseEvaluation decoderReuseEvaluation) {
|
Format format, @Nullable DecoderReuseEvaluation decoderReuseEvaluation) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_INPUT_FORMAT_CHANGED,
|
AnalyticsListener.EVENT_AUDIO_INPUT_FORMAT_CHANGED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onAudioInputFormatChanged(eventTime, format, decoderReuseEvaluation);
|
listener.onAudioInputFormatChanged(eventTime, format, decoderReuseEvaluation);
|
||||||
@ -223,7 +236,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onAudioPositionAdvancing(long playoutStartSystemTimeMs) {
|
public final void onAudioPositionAdvancing(long playoutStartSystemTimeMs) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_POSITION_ADVANCING,
|
AnalyticsListener.EVENT_AUDIO_POSITION_ADVANCING,
|
||||||
listener -> listener.onAudioPositionAdvancing(eventTime, playoutStartSystemTimeMs));
|
listener -> listener.onAudioPositionAdvancing(eventTime, playoutStartSystemTimeMs));
|
||||||
}
|
}
|
||||||
@ -232,7 +246,8 @@ public class AnalyticsCollector
|
|||||||
public final void onAudioUnderrun(
|
public final void onAudioUnderrun(
|
||||||
int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
|
int bufferSize, long bufferSizeMs, long elapsedSinceLastFeedMs) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_UNDERRUN,
|
AnalyticsListener.EVENT_AUDIO_UNDERRUN,
|
||||||
listener ->
|
listener ->
|
||||||
listener.onAudioUnderrun(eventTime, bufferSize, bufferSizeMs, elapsedSinceLastFeedMs));
|
listener.onAudioUnderrun(eventTime, bufferSize, bufferSizeMs, elapsedSinceLastFeedMs));
|
||||||
@ -241,7 +256,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onAudioDecoderReleased(String decoderName) {
|
public final void onAudioDecoderReleased(String decoderName) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_DECODER_RELEASED,
|
AnalyticsListener.EVENT_AUDIO_DECODER_RELEASED,
|
||||||
listener -> listener.onAudioDecoderReleased(eventTime, decoderName));
|
listener -> listener.onAudioDecoderReleased(eventTime, decoderName));
|
||||||
}
|
}
|
||||||
@ -250,7 +266,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onAudioDisabled(DecoderCounters counters) {
|
public final void onAudioDisabled(DecoderCounters counters) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_DISABLED,
|
AnalyticsListener.EVENT_AUDIO_DISABLED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onAudioDisabled(eventTime, counters);
|
listener.onAudioDisabled(eventTime, counters);
|
||||||
@ -263,7 +280,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onAudioSessionId(int audioSessionId) {
|
public final void onAudioSessionId(int audioSessionId) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_SESSION_ID,
|
AnalyticsListener.EVENT_AUDIO_SESSION_ID,
|
||||||
listener -> listener.onAudioSessionId(eventTime, audioSessionId));
|
listener -> listener.onAudioSessionId(eventTime, audioSessionId));
|
||||||
}
|
}
|
||||||
@ -271,7 +289,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public void onAudioAttributesChanged(AudioAttributes audioAttributes) {
|
public void onAudioAttributesChanged(AudioAttributes audioAttributes) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_ATTRIBUTES_CHANGED,
|
AnalyticsListener.EVENT_AUDIO_ATTRIBUTES_CHANGED,
|
||||||
listener -> listener.onAudioAttributesChanged(eventTime, audioAttributes));
|
listener -> listener.onAudioAttributesChanged(eventTime, audioAttributes));
|
||||||
}
|
}
|
||||||
@ -279,7 +298,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public void onSkipSilenceEnabledChanged(boolean skipSilenceEnabled) {
|
public void onSkipSilenceEnabledChanged(boolean skipSilenceEnabled) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_SKIP_SILENCE_ENABLED_CHANGED,
|
AnalyticsListener.EVENT_SKIP_SILENCE_ENABLED_CHANGED,
|
||||||
listener -> listener.onSkipSilenceEnabledChanged(eventTime, skipSilenceEnabled));
|
listener -> listener.onSkipSilenceEnabledChanged(eventTime, skipSilenceEnabled));
|
||||||
}
|
}
|
||||||
@ -287,7 +307,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public void onAudioSinkError(Exception audioSinkError) {
|
public void onAudioSinkError(Exception audioSinkError) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_AUDIO_SINK_ERROR,
|
AnalyticsListener.EVENT_AUDIO_SINK_ERROR,
|
||||||
listener -> listener.onAudioSinkError(eventTime, audioSinkError));
|
listener -> listener.onAudioSinkError(eventTime, audioSinkError));
|
||||||
}
|
}
|
||||||
@ -295,7 +316,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public void onVolumeChanged(float audioVolume) {
|
public void onVolumeChanged(float audioVolume) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VOLUME_CHANGED,
|
AnalyticsListener.EVENT_VOLUME_CHANGED,
|
||||||
listener -> listener.onVolumeChanged(eventTime, audioVolume));
|
listener -> listener.onVolumeChanged(eventTime, audioVolume));
|
||||||
}
|
}
|
||||||
@ -306,7 +328,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onVideoEnabled(DecoderCounters counters) {
|
public final void onVideoEnabled(DecoderCounters counters) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VIDEO_ENABLED,
|
AnalyticsListener.EVENT_VIDEO_ENABLED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onVideoEnabled(eventTime, counters);
|
listener.onVideoEnabled(eventTime, counters);
|
||||||
@ -319,7 +342,8 @@ public class AnalyticsCollector
|
|||||||
public final void onVideoDecoderInitialized(
|
public final void onVideoDecoderInitialized(
|
||||||
String decoderName, long initializedTimestampMs, long initializationDurationMs) {
|
String decoderName, long initializedTimestampMs, long initializationDurationMs) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VIDEO_DECODER_INITIALIZED,
|
AnalyticsListener.EVENT_VIDEO_DECODER_INITIALIZED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onVideoDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
listener.onVideoDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
||||||
@ -333,7 +357,8 @@ public class AnalyticsCollector
|
|||||||
public final void onVideoInputFormatChanged(
|
public final void onVideoInputFormatChanged(
|
||||||
Format format, @Nullable DecoderReuseEvaluation decoderReuseEvaluation) {
|
Format format, @Nullable DecoderReuseEvaluation decoderReuseEvaluation) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VIDEO_INPUT_FORMAT_CHANGED,
|
AnalyticsListener.EVENT_VIDEO_INPUT_FORMAT_CHANGED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onVideoInputFormatChanged(eventTime, format, decoderReuseEvaluation);
|
listener.onVideoInputFormatChanged(eventTime, format, decoderReuseEvaluation);
|
||||||
@ -344,7 +369,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onDroppedFrames(int count, long elapsedMs) {
|
public final void onDroppedFrames(int count, long elapsedMs) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_DROPPED_VIDEO_FRAMES,
|
AnalyticsListener.EVENT_DROPPED_VIDEO_FRAMES,
|
||||||
listener -> listener.onDroppedVideoFrames(eventTime, count, elapsedMs));
|
listener -> listener.onDroppedVideoFrames(eventTime, count, elapsedMs));
|
||||||
}
|
}
|
||||||
@ -352,7 +378,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onVideoDecoderReleased(String decoderName) {
|
public final void onVideoDecoderReleased(String decoderName) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VIDEO_DECODER_RELEASED,
|
AnalyticsListener.EVENT_VIDEO_DECODER_RELEASED,
|
||||||
listener -> listener.onVideoDecoderReleased(eventTime, decoderName));
|
listener -> listener.onVideoDecoderReleased(eventTime, decoderName));
|
||||||
}
|
}
|
||||||
@ -361,7 +388,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onVideoDisabled(DecoderCounters counters) {
|
public final void onVideoDisabled(DecoderCounters counters) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VIDEO_DISABLED,
|
AnalyticsListener.EVENT_VIDEO_DISABLED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onVideoDisabled(eventTime, counters);
|
listener.onVideoDisabled(eventTime, counters);
|
||||||
@ -372,7 +400,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onRenderedFirstFrame(@Nullable Surface surface) {
|
public final void onRenderedFirstFrame(@Nullable Surface surface) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_RENDERED_FIRST_FRAME,
|
AnalyticsListener.EVENT_RENDERED_FIRST_FRAME,
|
||||||
listener -> listener.onRenderedFirstFrame(eventTime, surface));
|
listener -> listener.onRenderedFirstFrame(eventTime, surface));
|
||||||
}
|
}
|
||||||
@ -380,7 +409,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onVideoFrameProcessingOffset(long totalProcessingOffsetUs, int frameCount) {
|
public final void onVideoFrameProcessingOffset(long totalProcessingOffsetUs, int frameCount) {
|
||||||
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
EventTime eventTime = generatePlayingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VIDEO_FRAME_PROCESSING_OFFSET,
|
AnalyticsListener.EVENT_VIDEO_FRAME_PROCESSING_OFFSET,
|
||||||
listener ->
|
listener ->
|
||||||
listener.onVideoFrameProcessingOffset(eventTime, totalProcessingOffsetUs, frameCount));
|
listener.onVideoFrameProcessingOffset(eventTime, totalProcessingOffsetUs, frameCount));
|
||||||
@ -397,7 +427,8 @@ public class AnalyticsCollector
|
|||||||
public final void onVideoSizeChanged(
|
public final void onVideoSizeChanged(
|
||||||
int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_VIDEO_SIZE_CHANGED,
|
AnalyticsListener.EVENT_VIDEO_SIZE_CHANGED,
|
||||||
listener ->
|
listener ->
|
||||||
listener.onVideoSizeChanged(
|
listener.onVideoSizeChanged(
|
||||||
@ -407,7 +438,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public void onSurfaceSizeChanged(int width, int height) {
|
public void onSurfaceSizeChanged(int width, int height) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_SURFACE_SIZE_CHANGED,
|
AnalyticsListener.EVENT_SURFACE_SIZE_CHANGED,
|
||||||
listener -> listener.onSurfaceSizeChanged(eventTime, width, height));
|
listener -> listener.onSurfaceSizeChanged(eventTime, width, height));
|
||||||
}
|
}
|
||||||
@ -421,7 +453,8 @@ public class AnalyticsCollector
|
|||||||
LoadEventInfo loadEventInfo,
|
LoadEventInfo loadEventInfo,
|
||||||
MediaLoadData mediaLoadData) {
|
MediaLoadData mediaLoadData) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_LOAD_STARTED,
|
AnalyticsListener.EVENT_LOAD_STARTED,
|
||||||
listener -> listener.onLoadStarted(eventTime, loadEventInfo, mediaLoadData));
|
listener -> listener.onLoadStarted(eventTime, loadEventInfo, mediaLoadData));
|
||||||
}
|
}
|
||||||
@ -433,7 +466,8 @@ public class AnalyticsCollector
|
|||||||
LoadEventInfo loadEventInfo,
|
LoadEventInfo loadEventInfo,
|
||||||
MediaLoadData mediaLoadData) {
|
MediaLoadData mediaLoadData) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_LOAD_COMPLETED,
|
AnalyticsListener.EVENT_LOAD_COMPLETED,
|
||||||
listener -> listener.onLoadCompleted(eventTime, loadEventInfo, mediaLoadData));
|
listener -> listener.onLoadCompleted(eventTime, loadEventInfo, mediaLoadData));
|
||||||
}
|
}
|
||||||
@ -445,7 +479,8 @@ public class AnalyticsCollector
|
|||||||
LoadEventInfo loadEventInfo,
|
LoadEventInfo loadEventInfo,
|
||||||
MediaLoadData mediaLoadData) {
|
MediaLoadData mediaLoadData) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_LOAD_CANCELED,
|
AnalyticsListener.EVENT_LOAD_CANCELED,
|
||||||
listener -> listener.onLoadCanceled(eventTime, loadEventInfo, mediaLoadData));
|
listener -> listener.onLoadCanceled(eventTime, loadEventInfo, mediaLoadData));
|
||||||
}
|
}
|
||||||
@ -459,7 +494,8 @@ public class AnalyticsCollector
|
|||||||
IOException error,
|
IOException error,
|
||||||
boolean wasCanceled) {
|
boolean wasCanceled) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_LOAD_ERROR,
|
AnalyticsListener.EVENT_LOAD_ERROR,
|
||||||
listener ->
|
listener ->
|
||||||
listener.onLoadError(eventTime, loadEventInfo, mediaLoadData, error, wasCanceled));
|
listener.onLoadError(eventTime, loadEventInfo, mediaLoadData, error, wasCanceled));
|
||||||
@ -469,7 +505,8 @@ public class AnalyticsCollector
|
|||||||
public final void onUpstreamDiscarded(
|
public final void onUpstreamDiscarded(
|
||||||
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {
|
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_UPSTREAM_DISCARDED,
|
AnalyticsListener.EVENT_UPSTREAM_DISCARDED,
|
||||||
listener -> listener.onUpstreamDiscarded(eventTime, mediaLoadData));
|
listener -> listener.onUpstreamDiscarded(eventTime, mediaLoadData));
|
||||||
}
|
}
|
||||||
@ -478,7 +515,8 @@ public class AnalyticsCollector
|
|||||||
public final void onDownstreamFormatChanged(
|
public final void onDownstreamFormatChanged(
|
||||||
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {
|
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, MediaLoadData mediaLoadData) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_DOWNSTREAM_FORMAT_CHANGED,
|
AnalyticsListener.EVENT_DOWNSTREAM_FORMAT_CHANGED,
|
||||||
listener -> listener.onDownstreamFormatChanged(eventTime, mediaLoadData));
|
listener -> listener.onDownstreamFormatChanged(eventTime, mediaLoadData));
|
||||||
}
|
}
|
||||||
@ -493,7 +531,8 @@ public class AnalyticsCollector
|
|||||||
public final void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
|
public final void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) {
|
||||||
mediaPeriodQueueTracker.onTimelineChanged(checkNotNull(player));
|
mediaPeriodQueueTracker.onTimelineChanged(checkNotNull(player));
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_TIMELINE_CHANGED,
|
AnalyticsListener.EVENT_TIMELINE_CHANGED,
|
||||||
listener -> listener.onTimelineChanged(eventTime, reason));
|
listener -> listener.onTimelineChanged(eventTime, reason));
|
||||||
}
|
}
|
||||||
@ -502,7 +541,8 @@ public class AnalyticsCollector
|
|||||||
public final void onMediaItemTransition(
|
public final void onMediaItemTransition(
|
||||||
@Nullable MediaItem mediaItem, @Player.MediaItemTransitionReason int reason) {
|
@Nullable MediaItem mediaItem, @Player.MediaItemTransitionReason int reason) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_MEDIA_ITEM_TRANSITION,
|
AnalyticsListener.EVENT_MEDIA_ITEM_TRANSITION,
|
||||||
listener -> listener.onMediaItemTransition(eventTime, mediaItem, reason));
|
listener -> listener.onMediaItemTransition(eventTime, mediaItem, reason));
|
||||||
}
|
}
|
||||||
@ -511,7 +551,8 @@ public class AnalyticsCollector
|
|||||||
public final void onTracksChanged(
|
public final void onTracksChanged(
|
||||||
TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
|
TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_TRACKS_CHANGED,
|
AnalyticsListener.EVENT_TRACKS_CHANGED,
|
||||||
listener -> listener.onTracksChanged(eventTime, trackGroups, trackSelections));
|
listener -> listener.onTracksChanged(eventTime, trackGroups, trackSelections));
|
||||||
}
|
}
|
||||||
@ -519,7 +560,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onStaticMetadataChanged(List<Metadata> metadataList) {
|
public final void onStaticMetadataChanged(List<Metadata> metadataList) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_STATIC_METADATA_CHANGED,
|
AnalyticsListener.EVENT_STATIC_METADATA_CHANGED,
|
||||||
listener -> listener.onStaticMetadataChanged(eventTime, metadataList));
|
listener -> listener.onStaticMetadataChanged(eventTime, metadataList));
|
||||||
}
|
}
|
||||||
@ -527,7 +569,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onIsLoadingChanged(boolean isLoading) {
|
public final void onIsLoadingChanged(boolean isLoading) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_IS_LOADING_CHANGED,
|
AnalyticsListener.EVENT_IS_LOADING_CHANGED,
|
||||||
listener -> listener.onIsLoadingChanged(eventTime, isLoading));
|
listener -> listener.onIsLoadingChanged(eventTime, isLoading));
|
||||||
}
|
}
|
||||||
@ -536,7 +579,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) {
|
public final void onPlayerStateChanged(boolean playWhenReady, @Player.State int playbackState) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
/* eventFlag= */ C.INDEX_UNSET,
|
/* eventFlag= */ C.INDEX_UNSET,
|
||||||
listener -> listener.onPlayerStateChanged(eventTime, playWhenReady, playbackState));
|
listener -> listener.onPlayerStateChanged(eventTime, playWhenReady, playbackState));
|
||||||
}
|
}
|
||||||
@ -544,7 +588,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onPlaybackStateChanged(@Player.State int state) {
|
public final void onPlaybackStateChanged(@Player.State int state) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_PLAYBACK_STATE_CHANGED,
|
AnalyticsListener.EVENT_PLAYBACK_STATE_CHANGED,
|
||||||
listener -> listener.onPlaybackStateChanged(eventTime, state));
|
listener -> listener.onPlaybackStateChanged(eventTime, state));
|
||||||
}
|
}
|
||||||
@ -553,7 +598,8 @@ public class AnalyticsCollector
|
|||||||
public final void onPlayWhenReadyChanged(
|
public final void onPlayWhenReadyChanged(
|
||||||
boolean playWhenReady, @Player.PlayWhenReadyChangeReason int reason) {
|
boolean playWhenReady, @Player.PlayWhenReadyChangeReason int reason) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_PLAY_WHEN_READY_CHANGED,
|
AnalyticsListener.EVENT_PLAY_WHEN_READY_CHANGED,
|
||||||
listener -> listener.onPlayWhenReadyChanged(eventTime, playWhenReady, reason));
|
listener -> listener.onPlayWhenReadyChanged(eventTime, playWhenReady, reason));
|
||||||
}
|
}
|
||||||
@ -562,7 +608,8 @@ public class AnalyticsCollector
|
|||||||
public void onPlaybackSuppressionReasonChanged(
|
public void onPlaybackSuppressionReasonChanged(
|
||||||
@PlaybackSuppressionReason int playbackSuppressionReason) {
|
@PlaybackSuppressionReason int playbackSuppressionReason) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
|
AnalyticsListener.EVENT_PLAYBACK_SUPPRESSION_REASON_CHANGED,
|
||||||
listener ->
|
listener ->
|
||||||
listener.onPlaybackSuppressionReasonChanged(eventTime, playbackSuppressionReason));
|
listener.onPlaybackSuppressionReasonChanged(eventTime, playbackSuppressionReason));
|
||||||
@ -571,7 +618,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public void onIsPlayingChanged(boolean isPlaying) {
|
public void onIsPlayingChanged(boolean isPlaying) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_IS_PLAYING_CHANGED,
|
AnalyticsListener.EVENT_IS_PLAYING_CHANGED,
|
||||||
listener -> listener.onIsPlayingChanged(eventTime, isPlaying));
|
listener -> listener.onIsPlayingChanged(eventTime, isPlaying));
|
||||||
}
|
}
|
||||||
@ -579,7 +627,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
public final void onRepeatModeChanged(@Player.RepeatMode int repeatMode) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_REPEAT_MODE_CHANGED,
|
AnalyticsListener.EVENT_REPEAT_MODE_CHANGED,
|
||||||
listener -> listener.onRepeatModeChanged(eventTime, repeatMode));
|
listener -> listener.onRepeatModeChanged(eventTime, repeatMode));
|
||||||
}
|
}
|
||||||
@ -587,7 +636,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
|
public final void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
|
AnalyticsListener.EVENT_SHUFFLE_MODE_ENABLED_CHANGED,
|
||||||
listener -> listener.onShuffleModeChanged(eventTime, shuffleModeEnabled));
|
listener -> listener.onShuffleModeChanged(eventTime, shuffleModeEnabled));
|
||||||
}
|
}
|
||||||
@ -598,8 +648,10 @@ public class AnalyticsCollector
|
|||||||
error.mediaPeriodId != null
|
error.mediaPeriodId != null
|
||||||
? generateEventTime(error.mediaPeriodId)
|
? generateEventTime(error.mediaPeriodId)
|
||||||
: generateCurrentPlayerMediaPeriodEventTime();
|
: generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
AnalyticsListener.EVENT_PLAYER_ERROR, listener -> listener.onPlayerError(eventTime, error));
|
eventTime,
|
||||||
|
AnalyticsListener.EVENT_PLAYER_ERROR,
|
||||||
|
listener -> listener.onPlayerError(eventTime, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -609,7 +661,8 @@ public class AnalyticsCollector
|
|||||||
}
|
}
|
||||||
mediaPeriodQueueTracker.onPositionDiscontinuity(checkNotNull(player));
|
mediaPeriodQueueTracker.onPositionDiscontinuity(checkNotNull(player));
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_POSITION_DISCONTINUITY,
|
AnalyticsListener.EVENT_POSITION_DISCONTINUITY,
|
||||||
listener -> listener.onPositionDiscontinuity(eventTime, reason));
|
listener -> listener.onPositionDiscontinuity(eventTime, reason));
|
||||||
}
|
}
|
||||||
@ -617,7 +670,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
public final void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_PLAYBACK_PARAMETERS_CHANGED,
|
AnalyticsListener.EVENT_PLAYBACK_PARAMETERS_CHANGED,
|
||||||
listener -> listener.onPlaybackParametersChanged(eventTime, playbackParameters));
|
listener -> listener.onPlaybackParametersChanged(eventTime, playbackParameters));
|
||||||
}
|
}
|
||||||
@ -626,8 +680,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onSeekProcessed() {
|
public final void onSeekProcessed() {
|
||||||
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
/* eventFlag= */ C.INDEX_UNSET, listener -> listener.onSeekProcessed(eventTime));
|
eventTime, /* eventFlag= */ C.INDEX_UNSET, listener -> listener.onSeekProcessed(eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
// BandwidthMeter.Listener implementation.
|
// BandwidthMeter.Listener implementation.
|
||||||
@ -635,7 +689,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
|
public final void onBandwidthSample(int elapsedMs, long bytes, long bitrate) {
|
||||||
EventTime eventTime = generateLoadingMediaPeriodEventTime();
|
EventTime eventTime = generateLoadingMediaPeriodEventTime();
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_BANDWIDTH_ESTIMATE,
|
AnalyticsListener.EVENT_BANDWIDTH_ESTIMATE,
|
||||||
listener -> listener.onBandwidthEstimate(eventTime, elapsedMs, bytes, bitrate));
|
listener -> listener.onBandwidthEstimate(eventTime, elapsedMs, bytes, bitrate));
|
||||||
}
|
}
|
||||||
@ -645,7 +700,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onDrmSessionAcquired(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
public final void onDrmSessionAcquired(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_DRM_SESSION_ACQUIRED,
|
AnalyticsListener.EVENT_DRM_SESSION_ACQUIRED,
|
||||||
listener -> listener.onDrmSessionAcquired(eventTime));
|
listener -> listener.onDrmSessionAcquired(eventTime));
|
||||||
}
|
}
|
||||||
@ -653,15 +709,18 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onDrmKeysLoaded(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
public final void onDrmKeysLoaded(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
AnalyticsListener.EVENT_DRM_KEYS_LOADED, listener -> listener.onDrmKeysLoaded(eventTime));
|
eventTime,
|
||||||
|
AnalyticsListener.EVENT_DRM_KEYS_LOADED,
|
||||||
|
listener -> listener.onDrmKeysLoaded(eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onDrmSessionManagerError(
|
public final void onDrmSessionManagerError(
|
||||||
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, Exception error) {
|
int windowIndex, @Nullable MediaPeriodId mediaPeriodId, Exception error) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_DRM_SESSION_MANAGER_ERROR,
|
AnalyticsListener.EVENT_DRM_SESSION_MANAGER_ERROR,
|
||||||
listener -> listener.onDrmSessionManagerError(eventTime, error));
|
listener -> listener.onDrmSessionManagerError(eventTime, error));
|
||||||
}
|
}
|
||||||
@ -669,7 +728,8 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onDrmKeysRestored(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
public final void onDrmKeysRestored(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_DRM_KEYS_RESTORED,
|
AnalyticsListener.EVENT_DRM_KEYS_RESTORED,
|
||||||
listener -> listener.onDrmKeysRestored(eventTime));
|
listener -> listener.onDrmKeysRestored(eventTime));
|
||||||
}
|
}
|
||||||
@ -677,20 +737,31 @@ public class AnalyticsCollector
|
|||||||
@Override
|
@Override
|
||||||
public final void onDrmKeysRemoved(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
public final void onDrmKeysRemoved(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
AnalyticsListener.EVENT_DRM_KEYS_REMOVED, listener -> listener.onDrmKeysRemoved(eventTime));
|
eventTime,
|
||||||
|
AnalyticsListener.EVENT_DRM_KEYS_REMOVED,
|
||||||
|
listener -> listener.onDrmKeysRemoved(eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
public final void onDrmSessionReleased(int windowIndex, @Nullable MediaPeriodId mediaPeriodId) {
|
||||||
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
EventTime eventTime = generateMediaPeriodEventTime(windowIndex, mediaPeriodId);
|
||||||
listeners.sendEvent(
|
sendEvent(
|
||||||
|
eventTime,
|
||||||
AnalyticsListener.EVENT_DRM_SESSION_RELEASED,
|
AnalyticsListener.EVENT_DRM_SESSION_RELEASED,
|
||||||
listener -> listener.onDrmSessionReleased(eventTime));
|
listener -> listener.onDrmSessionReleased(eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
|
|
||||||
|
private void sendEvent(
|
||||||
|
EventTime eventTime,
|
||||||
|
@AnalyticsListener.EventFlags int eventFlag,
|
||||||
|
ListenerSet.Event<AnalyticsListener> eventInvocation) {
|
||||||
|
eventTimes.put(eventFlag, eventTime);
|
||||||
|
listeners.sendEvent(eventFlag, eventInvocation);
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns a new {@link EventTime} for the specified timeline, window and media period id. */
|
/** Returns a new {@link EventTime} for the specified timeline, window and media period id. */
|
||||||
@RequiresNonNull("player")
|
@RequiresNonNull("player")
|
||||||
protected EventTime generateEventTime(
|
protected EventTime generateEventTime(
|
||||||
|
@ -15,7 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.android.exoplayer2.analytics;
|
package com.google.android.exoplayer2.analytics;
|
||||||
|
|
||||||
|
import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||||
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@ -63,6 +66,38 @@ public interface AnalyticsListener {
|
|||||||
|
|
||||||
/** A set of {@link EventFlags}. */
|
/** A set of {@link EventFlags}. */
|
||||||
final class Events extends MutableFlags {
|
final class Events extends MutableFlags {
|
||||||
|
|
||||||
|
private final SparseArray<EventTime> eventTimes;
|
||||||
|
|
||||||
|
/** Creates the set of event flags. */
|
||||||
|
public Events() {
|
||||||
|
eventTimes = new SparseArray<>(/* initialCapacity= */ 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link EventTime} for the specified event.
|
||||||
|
*
|
||||||
|
* @param event The {@link EventFlags event}.
|
||||||
|
* @return The {@link EventTime} of this event.
|
||||||
|
*/
|
||||||
|
public EventTime getEventTime(@EventFlags int event) {
|
||||||
|
return checkNotNull(eventTimes.get(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@link EventTime} values for events recorded in this set.
|
||||||
|
*
|
||||||
|
* @param eventTimes A map from {@link EventFlags} to {@link EventTime}. Must at least contain
|
||||||
|
* all the events recorded in this set.
|
||||||
|
*/
|
||||||
|
public void setEventTimes(SparseArray<EventTime> eventTimes) {
|
||||||
|
this.eventTimes.clear();
|
||||||
|
for (int i = 0; i < size(); i++) {
|
||||||
|
@EventFlags int eventFlag = get(i);
|
||||||
|
this.eventTimes.append(eventFlag, checkNotNull(eventTimes.get(eventFlag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the given event occurred.
|
* Returns whether the given event occurred.
|
||||||
*
|
*
|
||||||
|
@ -8849,7 +8849,7 @@ public final class ExoPlayerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onStateChangedFlags_correspondToListenerCalls() throws Exception {
|
public void onEvents_correspondToListenerCalls() throws Exception {
|
||||||
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
ExoPlayer player = new TestExoPlayerBuilder(context).build();
|
||||||
EventListener listener = mock(EventListener.class);
|
EventListener listener = mock(EventListener.class);
|
||||||
player.addListener(listener);
|
player.addListener(listener);
|
||||||
@ -8897,13 +8897,14 @@ public final class ExoPlayerTest {
|
|||||||
assertThat(events.contains(Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED)).isTrue();
|
assertThat(events.contains(Player.EVENT_SHUFFLE_MODE_ENABLED_CHANGED)).isTrue();
|
||||||
|
|
||||||
// Ensure all other events are called (even though we can't control how exactly they are
|
// Ensure all other events are called (even though we can't control how exactly they are
|
||||||
// combined together in onStateChanged calls).
|
// combined together in onEvents calls).
|
||||||
player.prepare();
|
player.prepare();
|
||||||
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
|
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
|
||||||
player.play();
|
player.play();
|
||||||
player.setMediaItem(MediaItem.fromUri("http://this-will-throw-an-exception.mp4"));
|
player.setMediaItem(MediaItem.fromUri("http://this-will-throw-an-exception.mp4"));
|
||||||
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_IDLE);
|
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_IDLE);
|
||||||
ShadowLooper.runMainLooperToNextTask();
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
player.release();
|
||||||
|
|
||||||
// Verify that all callbacks have been called at least once.
|
// Verify that all callbacks have been called at least once.
|
||||||
verify(listener, atLeastOnce()).onTimelineChanged(any(), anyInt());
|
verify(listener, atLeastOnce()).onTimelineChanged(any(), anyInt());
|
||||||
@ -8920,7 +8921,7 @@ public final class ExoPlayerTest {
|
|||||||
verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean());
|
verify(listener, atLeastOnce()).onIsPlayingChanged(anyBoolean());
|
||||||
verify(listener, atLeastOnce()).onPlayerError(any());
|
verify(listener, atLeastOnce()).onPlayerError(any());
|
||||||
|
|
||||||
// Verify all the same events have been recorded with onStateChanged.
|
// Verify all the same events have been recorded with onEvents.
|
||||||
verify(listener, atLeastOnce()).onEvents(eq(player), eventCaptor.capture());
|
verify(listener, atLeastOnce()).onEvents(eq(player), eventCaptor.capture());
|
||||||
List<Player.Events> allEvents = eventCaptor.getAllValues();
|
List<Player.Events> allEvents = eventCaptor.getAllValues();
|
||||||
assertThat(containsEvent(allEvents, Player.EVENT_TIMELINE_CHANGED)).isTrue();
|
assertThat(containsEvent(allEvents, Player.EVENT_TIMELINE_CHANGED)).isTrue();
|
||||||
|
@ -28,11 +28,19 @@ import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_DR
|
|||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_DRM_SESSION_RELEASED;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_DRM_SESSION_RELEASED;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_DROPPED_VIDEO_FRAMES;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_DROPPED_VIDEO_FRAMES;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_IS_LOADING_CHANGED;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_IS_LOADING_CHANGED;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_IS_PLAYING_CHANGED;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_LOAD_CANCELED;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_LOAD_COMPLETED;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_LOAD_COMPLETED;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_LOAD_ERROR;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_LOAD_STARTED;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_LOAD_STARTED;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_MEDIA_ITEM_TRANSITION;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_PLAYBACK_PARAMETERS_CHANGED;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_PLAYBACK_STATE_CHANGED;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_PLAYER_ERROR;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_PLAYER_ERROR;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_PLAY_WHEN_READY_CHANGED;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_POSITION_DISCONTINUITY;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_POSITION_DISCONTINUITY;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_RENDERED_FIRST_FRAME;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_RENDERED_FIRST_FRAME;
|
||||||
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_STATIC_METADATA_CHANGED;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_TIMELINE_CHANGED;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_TIMELINE_CHANGED;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_TRACKS_CHANGED;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_TRACKS_CHANGED;
|
||||||
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_VIDEO_DECODER_INITIALIZED;
|
import static com.google.android.exoplayer2.analytics.AnalyticsListener.EVENT_VIDEO_DECODER_INITIALIZED;
|
||||||
@ -45,11 +53,18 @@ import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSample
|
|||||||
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.atLeastOnce;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
@ -57,6 +72,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||||||
import com.google.android.exoplayer2.C;
|
import com.google.android.exoplayer2.C;
|
||||||
import com.google.android.exoplayer2.ExoPlaybackException;
|
import com.google.android.exoplayer2.ExoPlaybackException;
|
||||||
import com.google.android.exoplayer2.Format;
|
import com.google.android.exoplayer2.Format;
|
||||||
|
import com.google.android.exoplayer2.MediaItem;
|
||||||
import com.google.android.exoplayer2.PlaybackParameters;
|
import com.google.android.exoplayer2.PlaybackParameters;
|
||||||
import com.google.android.exoplayer2.Player;
|
import com.google.android.exoplayer2.Player;
|
||||||
import com.google.android.exoplayer2.Renderer;
|
import com.google.android.exoplayer2.Renderer;
|
||||||
@ -72,6 +88,7 @@ import com.google.android.exoplayer2.drm.ExoMediaDrm;
|
|||||||
import com.google.android.exoplayer2.drm.MediaDrmCallback;
|
import com.google.android.exoplayer2.drm.MediaDrmCallback;
|
||||||
import com.google.android.exoplayer2.drm.MediaDrmCallbackException;
|
import com.google.android.exoplayer2.drm.MediaDrmCallbackException;
|
||||||
import com.google.android.exoplayer2.metadata.Metadata;
|
import com.google.android.exoplayer2.metadata.Metadata;
|
||||||
|
import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper;
|
||||||
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
|
||||||
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;
|
||||||
@ -89,9 +106,11 @@ import com.google.android.exoplayer2.testutil.FakeRenderer;
|
|||||||
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
import com.google.android.exoplayer2.testutil.FakeTimeline;
|
||||||
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
|
import com.google.android.exoplayer2.testutil.FakeTimeline.TimelineWindowDefinition;
|
||||||
import com.google.android.exoplayer2.testutil.FakeVideoRenderer;
|
import com.google.android.exoplayer2.testutil.FakeVideoRenderer;
|
||||||
|
import com.google.android.exoplayer2.testutil.TestExoPlayerBuilder;
|
||||||
import com.google.android.exoplayer2.testutil.TestUtil;
|
import com.google.android.exoplayer2.testutil.TestUtil;
|
||||||
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
|
||||||
import com.google.android.exoplayer2.util.Clock;
|
import com.google.android.exoplayer2.util.Clock;
|
||||||
|
import com.google.android.exoplayer2.util.MimeTypes;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -103,8 +122,10 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
|
import org.robolectric.shadows.ShadowLooper;
|
||||||
|
|
||||||
/** Integration test for {@link AnalyticsCollector}. */
|
/** Integration test for {@link AnalyticsCollector}. */
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@ -1601,6 +1622,264 @@ public final class AnalyticsCollectorTest {
|
|||||||
assertThat(listener.getEvents(EVENT_PLAYER_ERROR)).containsExactly(period1);
|
assertThat(listener.getEvents(EVENT_PLAYER_ERROR)).containsExactly(period1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void onEvents_isReportedWithCorrectEventTimes() throws Exception {
|
||||||
|
SimpleExoPlayer player =
|
||||||
|
new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).build();
|
||||||
|
AnalyticsListener listener = mock(AnalyticsListener.class);
|
||||||
|
Format[] formats =
|
||||||
|
new Format[] {
|
||||||
|
new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_H264).build(),
|
||||||
|
new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_AAC).build()
|
||||||
|
};
|
||||||
|
player.addAnalyticsListener(listener);
|
||||||
|
|
||||||
|
// Trigger some simultaneous events.
|
||||||
|
player.setMediaSource(new FakeMediaSource(new FakeTimeline(/* windowCount= */ 1), formats));
|
||||||
|
player.seekTo(2_000);
|
||||||
|
player.setPlaybackParameters(new PlaybackParameters(/* speed= */ 2.0f));
|
||||||
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
|
||||||
|
// Move to another item and fail with a third one to trigger events with different EventTimes.
|
||||||
|
player.prepare();
|
||||||
|
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_READY);
|
||||||
|
player.addMediaSource(new FakeMediaSource(new FakeTimeline(/* windowCount= */ 1), formats));
|
||||||
|
player.play();
|
||||||
|
TestPlayerRunHelper.runUntilPositionDiscontinuity(
|
||||||
|
player, Player.DISCONTINUITY_REASON_PERIOD_TRANSITION);
|
||||||
|
player.setMediaItem(MediaItem.fromUri("http://this-will-throw-an-exception.mp4"));
|
||||||
|
TestPlayerRunHelper.runUntilPlaybackState(player, Player.STATE_IDLE);
|
||||||
|
ShadowLooper.runMainLooperToNextTask();
|
||||||
|
player.release();
|
||||||
|
|
||||||
|
// Verify that expected individual callbacks have been called and capture EventTimes.
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualTimelineChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onTimelineChanged(individualTimelineChangedEventTimes.capture(), anyInt());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualMediaItemTransitionEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onMediaItemTransition(individualMediaItemTransitionEventTimes.capture(), any(), anyInt());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualPositionDiscontinuityEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onPositionDiscontinuity(individualPositionDiscontinuityEventTimes.capture(), anyInt());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualPlaybackStateChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onPlaybackStateChanged(individualPlaybackStateChangedEventTimes.capture(), anyInt());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualIsLoadingChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onIsLoadingChanged(individualIsLoadingChangedEventTimes.capture(), anyBoolean());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualTracksChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onTracksChanged(individualTracksChangedEventTimes.capture(), any(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayWhenReadyChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onPlayWhenReadyChanged(
|
||||||
|
individualPlayWhenReadyChangedEventTimes.capture(), anyBoolean(), anyInt());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualIsPlayingChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onIsPlayingChanged(individualIsPlayingChangedEventTimes.capture(), anyBoolean());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualPlayerErrorEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce()).onPlayerError(individualPlayerErrorEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualPlaybackParametersChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onPlaybackParametersChanged(
|
||||||
|
individualPlaybackParametersChangedEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualLoadStartedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onLoadStarted(individualLoadStartedEventTimes.capture(), any(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualLoadCompletedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onLoadCompleted(individualLoadCompletedEventTimes.capture(), any(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualLoadErrorEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onLoadError(individualLoadErrorEventTimes.capture(), any(), any(), any(), anyBoolean());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoEnabledEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onVideoEnabled(individualVideoEnabledEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualAudioEnabledEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onAudioEnabled(individualAudioEnabledEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualStaticMetadataChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onStaticMetadataChanged(individualStaticMetadataChangedEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualDownstreamFormatChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onDownstreamFormatChanged(individualDownstreamFormatChangedEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoInputFormatChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onVideoInputFormatChanged(
|
||||||
|
individualVideoInputFormatChangedEventTimes.capture(), any(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualAudioInputFormatChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onAudioInputFormatChanged(
|
||||||
|
individualAudioInputFormatChangedEventTimes.capture(), any(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoDecoderInitializedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onVideoDecoderInitialized(
|
||||||
|
individualVideoDecoderInitializedEventTimes.capture(), any(), anyLong());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualAudioDecoderInitializedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onAudioDecoderInitialized(
|
||||||
|
individualAudioDecoderInitializedEventTimes.capture(), any(), anyLong());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoDisabledEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onVideoDisabled(individualVideoDisabledEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualAudioDisabledEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onAudioDisabled(individualAudioDisabledEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualRenderedFirstFrameEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onRenderedFirstFrame(individualRenderedFirstFrameEventTimes.capture(), any());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoSizeChangedEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onVideoSizeChanged(
|
||||||
|
individualVideoSizeChangedEventTimes.capture(),
|
||||||
|
anyInt(),
|
||||||
|
anyInt(),
|
||||||
|
anyInt(),
|
||||||
|
anyFloat());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualAudioPositionAdvancingEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onAudioPositionAdvancing(individualAudioPositionAdvancingEventTimes.capture(), anyLong());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoProcessingOffsetEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onVideoFrameProcessingOffset(
|
||||||
|
individualVideoProcessingOffsetEventTimes.capture(), anyLong(), anyInt());
|
||||||
|
ArgumentCaptor<AnalyticsListener.EventTime> individualDroppedFramesEventTimes =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
|
verify(listener, atLeastOnce())
|
||||||
|
.onDroppedVideoFrames(individualDroppedFramesEventTimes.capture(), anyInt(), anyLong());
|
||||||
|
|
||||||
|
// Verify the EventTimes reported with onEvents are a non-empty subset of the individual
|
||||||
|
// callback EventTimes. We can only assert they are a non-empty subset because there may be
|
||||||
|
// multiple events of the same type arriving in the same message queue iteration.
|
||||||
|
ArgumentCaptor<AnalyticsListener.Events> eventsCaptor =
|
||||||
|
ArgumentCaptor.forClass(AnalyticsListener.Events.class);
|
||||||
|
verify(listener, atLeastOnce()).onEvents(eq(player), eventsCaptor.capture());
|
||||||
|
SparseArray<List<AnalyticsListener.EventTime>> onEventsEventTimes = new SparseArray<>();
|
||||||
|
for (AnalyticsListener.Events events : eventsCaptor.getAllValues()) {
|
||||||
|
for (int i = 0; i < events.size(); i++) {
|
||||||
|
@AnalyticsListener.EventFlags int event = events.get(i);
|
||||||
|
if (onEventsEventTimes.get(event) == null) {
|
||||||
|
onEventsEventTimes.put(event, new ArrayList<>());
|
||||||
|
}
|
||||||
|
onEventsEventTimes.get(event).add(events.getEventTime(event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SparseArray.get returns null if the key doesn't exist, thus verifying the sets are non-empty.
|
||||||
|
assertThat(individualTimelineChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_TIMELINE_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualMediaItemTransitionEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_MEDIA_ITEM_TRANSITION))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualPositionDiscontinuityEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_POSITION_DISCONTINUITY))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualPlaybackStateChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_PLAYBACK_STATE_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualIsLoadingChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_IS_LOADING_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualTracksChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_TRACKS_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualPlayWhenReadyChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_PLAY_WHEN_READY_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualIsPlayingChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_IS_PLAYING_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualPlayerErrorEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_PLAYER_ERROR))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualPlaybackParametersChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_PLAYBACK_PARAMETERS_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualLoadStartedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_LOAD_STARTED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualLoadCompletedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_LOAD_COMPLETED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualLoadErrorEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_LOAD_ERROR))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualVideoEnabledEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_VIDEO_ENABLED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualAudioEnabledEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_AUDIO_ENABLED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualStaticMetadataChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_STATIC_METADATA_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualDownstreamFormatChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_DOWNSTREAM_FORMAT_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualVideoInputFormatChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_VIDEO_INPUT_FORMAT_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualAudioInputFormatChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_AUDIO_INPUT_FORMAT_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualVideoDecoderInitializedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_VIDEO_DECODER_INITIALIZED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualAudioDecoderInitializedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_AUDIO_DECODER_INITIALIZED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualVideoDisabledEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_VIDEO_DISABLED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualAudioDisabledEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_AUDIO_DISABLED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualRenderedFirstFrameEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_RENDERED_FIRST_FRAME))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualVideoSizeChangedEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_VIDEO_SIZE_CHANGED))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualAudioPositionAdvancingEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_AUDIO_POSITION_ADVANCING))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualVideoProcessingOffsetEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_VIDEO_FRAME_PROCESSING_OFFSET))
|
||||||
|
.inOrder();
|
||||||
|
assertThat(individualDroppedFramesEventTimes.getAllValues())
|
||||||
|
.containsAtLeastElementsIn(onEventsEventTimes.get(EVENT_DROPPED_VIDEO_FRAMES))
|
||||||
|
.inOrder();
|
||||||
|
}
|
||||||
|
|
||||||
private void populateEventIds(Timeline timeline) {
|
private void populateEventIds(Timeline timeline) {
|
||||||
period0 =
|
period0 =
|
||||||
new EventWindowAndPeriodId(
|
new EventWindowAndPeriodId(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user