use of com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime in project ExoPlayer by google.
the class DefaultPlaybackSessionManagerTest method updateSessions_withMediaPeriodId_ofOtherWindow_createsNewSession.
@Test
public void updateSessions_withMediaPeriodId_ofOtherWindow_createsNewSession() {
Timeline timeline = new FakeTimeline(/* windowCount= */
2);
MediaPeriodId mediaPeriodId1 = new MediaPeriodId(timeline.getUidOfPeriod(/* periodIndex= */
0), /* windowSequenceNumber= */
0);
MediaPeriodId mediaPeriodId2 = new MediaPeriodId(timeline.getUidOfPeriod(/* periodIndex= */
1), /* windowSequenceNumber= */
1);
EventTime eventTime1 = createEventTime(timeline, /* windowIndex= */
0, mediaPeriodId1);
EventTime eventTime2 = createEventTime(timeline, /* windowIndex= */
0, mediaPeriodId2);
sessionManager.updateSessions(eventTime1);
sessionManager.updateSessions(eventTime2);
ArgumentCaptor<String> sessionId1 = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> sessionId2 = ArgumentCaptor.forClass(String.class);
verify(mockListener).onSessionCreated(eq(eventTime1), sessionId1.capture());
verify(mockListener).onSessionCreated(eq(eventTime2), sessionId2.capture());
verify(mockListener).onSessionActive(eventTime1, sessionId1.getValue());
verifyNoMoreInteractions(mockListener);
assertThat(sessionId1).isNotEqualTo(sessionId2);
assertThat(sessionManager.getSessionForMediaPeriodId(timeline, mediaPeriodId1)).isEqualTo(sessionId1.getValue());
assertThat(sessionManager.getSessionForMediaPeriodId(timeline, mediaPeriodId2)).isEqualTo(sessionId2.getValue());
}
use of com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime in project ExoPlayer by google.
the class DefaultPlaybackSessionManagerTest method positionDiscontinuity_fromAdToAd_finishesPastAds_andNotifiesAdPlaybackStated.
@Test
public void positionDiscontinuity_fromAdToAd_finishesPastAds_andNotifiesAdPlaybackStated() {
Timeline adTimeline = new FakeTimeline(new TimelineWindowDefinition(/* periodCount= */
1, /* id= */
0, /* isSeekable= */
true, /* isDynamic= */
false, /* durationUs= */
10 * C.MICROS_PER_SECOND, new AdPlaybackState(/* adsId= */
new Object(), /* adGroupTimesUs=... */
0, 5 * C.MICROS_PER_SECOND).withAdCount(/* adGroupIndex= */
0, /* adCount= */
1).withAdCount(/* adGroupIndex= */
1, /* adCount= */
1)));
EventTime adEventTime1 = createEventTime(adTimeline, /* windowIndex= */
0, new MediaPeriodId(adTimeline.getUidOfPeriod(/* periodIndex= */
0), /* adGroupIndex= */
0, /* adIndexInAdGroup= */
0, /* windowSequenceNumber= */
0));
EventTime adEventTime2 = createEventTime(adTimeline, /* windowIndex= */
0, new MediaPeriodId(adTimeline.getUidOfPeriod(/* periodIndex= */
0), /* adGroupIndex= */
1, /* adIndexInAdGroup= */
0, /* windowSequenceNumber= */
0));
EventTime contentEventTime = createEventTime(adTimeline, /* windowIndex= */
0, new MediaPeriodId(adTimeline.getUidOfPeriod(/* periodIndex= */
0), /* windowSequenceNumber= */
0, /* nextAdGroupIndex= */
1));
sessionManager.updateSessionsWithTimelineChange(contentEventTime);
sessionManager.updateSessions(adEventTime1);
sessionManager.updateSessions(adEventTime2);
String contentSessionId = sessionManager.getSessionForMediaPeriodId(adTimeline, contentEventTime.mediaPeriodId);
String adSessionId1 = sessionManager.getSessionForMediaPeriodId(adTimeline, adEventTime1.mediaPeriodId);
String adSessionId2 = sessionManager.getSessionForMediaPeriodId(adTimeline, adEventTime2.mediaPeriodId);
sessionManager.updateSessionsWithDiscontinuity(adEventTime1, Player.DISCONTINUITY_REASON_AUTO_TRANSITION);
sessionManager.updateSessionsWithDiscontinuity(adEventTime2, Player.DISCONTINUITY_REASON_SEEK);
verify(mockListener).onSessionCreated(eq(contentEventTime), anyString());
verify(mockListener).onSessionActive(eq(contentEventTime), anyString());
verify(mockListener).onSessionCreated(adEventTime1, adSessionId1);
verify(mockListener).onSessionCreated(adEventTime2, adSessionId2);
verify(mockListener).onAdPlaybackStarted(adEventTime1, contentSessionId, adSessionId1);
verify(mockListener).onSessionActive(adEventTime1, adSessionId1);
verify(mockListener).onSessionFinished(adEventTime2, adSessionId1, /* automaticTransitionToNextPlayback= */
false);
verify(mockListener).onAdPlaybackStarted(adEventTime2, contentSessionId, adSessionId2);
verify(mockListener).onSessionActive(adEventTime2, adSessionId2);
verifyNoMoreInteractions(mockListener);
}
use of com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime in project ExoPlayer by google.
the class DefaultAnalyticsCollectorTest method release_withCallbacksArrivingAfterRelease_onPlayerReleasedForwardedLast.
@Test
public void release_withCallbacksArrivingAfterRelease_onPlayerReleasedForwardedLast() throws Exception {
FakeClock fakeClock = new FakeClock(/* initialTimeMs= */
0, /* isAutoAdvancing= */
true);
ExoPlayer exoPlayer = new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).setClock(fakeClock).build();
AnalyticsListener analyticsListener = spy(new AnalyticsListener() {
@Override
public void onVideoDisabled(EventTime eventTime, DecoderCounters decoderCounters) {
// Add delay in callback to test whether event timestamp and release timestamp are
// in the correct order.
fakeClock.advanceTime(1);
}
});
exoPlayer.addAnalyticsListener(analyticsListener);
// Prepare with media to ensure video renderer is enabled.
exoPlayer.setMediaSource(new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT));
exoPlayer.prepare();
TestPlayerRunHelper.runUntilPlaybackState(exoPlayer, Player.STATE_READY);
// Release and add delay on releasing thread to verify timestamps of events.
exoPlayer.release();
long releaseTimeMs = fakeClock.currentTimeMillis();
fakeClock.advanceTime(1);
ShadowLooper.idleMainLooper();
// Verify video disable events and release events arrived in order.
ArgumentCaptor<AnalyticsListener.EventTime> videoDisabledEventTime = ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
ArgumentCaptor<AnalyticsListener.EventTime> releasedEventTime = ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
InOrder inOrder = inOrder(analyticsListener);
inOrder.verify(analyticsListener).onVideoDisabled(videoDisabledEventTime.capture(), any());
inOrder.verify(analyticsListener).onEvents(same(exoPlayer), argThat(events -> events.contains(EVENT_VIDEO_DISABLED)));
inOrder.verify(analyticsListener).onPlayerReleased(releasedEventTime.capture());
inOrder.verify(analyticsListener).onEvents(same(exoPlayer), argThat(events -> events.contains(EVENT_PLAYER_RELEASED)));
// Verify order of timestamps of these events.
// This verification is needed as a regression test against [internal ref: b/195396384]. The
// root cause of the regression was an onPlayerReleased timestamp that was less than the
// previously reported timestamps for other events triggered as part of the release.
long videoDisableTimeMs = videoDisabledEventTime.getValue().realtimeMs;
assertThat(videoDisableTimeMs).isGreaterThan(releaseTimeMs);
assertThat(releasedEventTime.getValue().realtimeMs).isGreaterThan(videoDisableTimeMs);
}
use of com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime in project ExoPlayer by google.
the class DefaultPlaybackSessionManager method updateSessions.
@Override
public synchronized void updateSessions(EventTime eventTime) {
Assertions.checkNotNull(listener);
if (eventTime.timeline.isEmpty()) {
// Don't try to create new sessions for empty timelines.
return;
}
@Nullable SessionDescriptor currentSession = sessions.get(currentSessionId);
if (eventTime.mediaPeriodId != null && currentSession != null) {
// If we receive an event associated with a media period, then it needs to be either part of
// the current window if it's the first created media period, or a window that will be played
// in the future. Otherwise, we know that it belongs to a session that was already finished
// and we can ignore the event.
boolean isAlreadyFinished = currentSession.windowSequenceNumber == C.INDEX_UNSET ? currentSession.windowIndex != eventTime.windowIndex : eventTime.mediaPeriodId.windowSequenceNumber < currentSession.windowSequenceNumber;
if (isAlreadyFinished) {
return;
}
}
SessionDescriptor eventSession = getOrAddSession(eventTime.windowIndex, eventTime.mediaPeriodId);
if (currentSessionId == null) {
currentSessionId = eventSession.sessionId;
}
if (eventTime.mediaPeriodId != null && eventTime.mediaPeriodId.isAd()) {
// Ensure that the content session for an ad session is created first.
MediaPeriodId contentMediaPeriodId = new MediaPeriodId(eventTime.mediaPeriodId.periodUid, eventTime.mediaPeriodId.windowSequenceNumber, eventTime.mediaPeriodId.adGroupIndex);
SessionDescriptor contentSession = getOrAddSession(eventTime.windowIndex, contentMediaPeriodId);
if (!contentSession.isCreated) {
contentSession.isCreated = true;
eventTime.timeline.getPeriodByUid(eventTime.mediaPeriodId.periodUid, period);
long adGroupPositionMs = Util.usToMs(period.getAdGroupTimeUs(eventTime.mediaPeriodId.adGroupIndex)) + period.getPositionInWindowMs();
// getAdGroupTimeUs may return 0 for prerolls despite period offset.
adGroupPositionMs = max(0, adGroupPositionMs);
EventTime eventTimeForContent = new EventTime(eventTime.realtimeMs, eventTime.timeline, eventTime.windowIndex, contentMediaPeriodId, /* eventPlaybackPositionMs= */
adGroupPositionMs, eventTime.currentTimeline, eventTime.currentWindowIndex, eventTime.currentMediaPeriodId, eventTime.currentPlaybackPositionMs, eventTime.totalBufferedDurationMs);
listener.onSessionCreated(eventTimeForContent, contentSession.sessionId);
}
}
if (!eventSession.isCreated) {
eventSession.isCreated = true;
listener.onSessionCreated(eventTime, eventSession.sessionId);
}
if (eventSession.sessionId.equals(currentSessionId) && !eventSession.isActive) {
eventSession.isActive = true;
listener.onSessionActive(eventTime, eventSession.sessionId);
}
}
use of com.google.android.exoplayer2.analytics.AnalyticsListener.EventTime in project ExoPlayer by google.
the class DefaultAnalyticsCollector method onMetadata.
@Override
public final void onMetadata(Metadata metadata) {
EventTime eventTime = generateCurrentPlayerMediaPeriodEventTime();
sendEvent(eventTime, AnalyticsListener.EVENT_METADATA, listener -> listener.onMetadata(eventTime, metadata));
}
Aggregations