From 7b5dcb3786f71726fed3acee62c46333ab02fd5a Mon Sep 17 00:00:00 2001 From: ibaker Date: Wed, 15 Dec 2021 19:56:42 +0000 Subject: [PATCH] Move ImaAdsLoader Player.Listener implementation to internal class PiperOrigin-RevId: 416613846 --- .../media3/exoplayer/ima/ImaAdsLoader.java | 75 ++++++++++--------- .../media3/exoplayer/ima/FakeExoPlayer.java | 26 +++++++ .../exoplayer/ima/ImaAdsLoaderTest.java | 26 +------ 3 files changed, 66 insertions(+), 61 deletions(-) diff --git a/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java b/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java index 740c0a8ee4..70049d5f63 100644 --- a/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java +++ b/libraries/exoplayer_ima/src/main/java/androidx/media3/exoplayer/ima/ImaAdsLoader.java @@ -88,7 +88,7 @@ import java.util.Set; * SDK Open Measurement documentation for more information. */ @UnstableApi -public final class ImaAdsLoader implements Player.Listener, AdsLoader { +public final class ImaAdsLoader implements AdsLoader { static { MediaLibraryInfo.registerModule("media3.exoplayer.ima"); @@ -388,6 +388,7 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { private final ImaUtil.Configuration configuration; private final Context context; private final ImaUtil.ImaFactory imaFactory; + private final PlayerListenerImpl playerListener; private final HashMap adTagLoaderByAdsId; private final HashMap adTagLoaderByAdsMediaSource; private final Timeline.Period period; @@ -404,6 +405,7 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { this.context = context.getApplicationContext(); this.configuration = configuration; this.imaFactory = imaFactory; + playerListener = new PlayerListenerImpl(); supportedMimeTypes = ImmutableList.of(); adTagLoaderByAdsId = new HashMap<>(); adTagLoaderByAdsMediaSource = new HashMap<>(); @@ -534,7 +536,7 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { if (player == null) { return; } - player.addListener(this); + player.addListener(playerListener); } @Nullable AdTagLoader adTagLoader = adTagLoaderByAdsId.get(adsId); @@ -556,7 +558,7 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { } if (player != null && adTagLoaderByAdsMediaSource.isEmpty()) { - player.removeListener(this); + player.removeListener(playerListener); player = null; } } @@ -564,7 +566,7 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { @Override public void release() { if (player != null) { - player.removeListener(this); + player.removeListener(playerListener); player = null; maybeUpdateCurrentAdTagLoader(); } @@ -604,37 +606,6 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { .handlePrepareError(adGroupIndex, adIndexInAdGroup, exception); } - // Player.Listener implementation. - - @Override - public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) { - if (timeline.isEmpty()) { - // The player is being reset or contains no media. - return; - } - maybeUpdateCurrentAdTagLoader(); - maybePreloadNextPeriodAds(); - } - - @Override - public void onPositionDiscontinuity( - Player.PositionInfo oldPosition, - Player.PositionInfo newPosition, - @Player.DiscontinuityReason int reason) { - maybeUpdateCurrentAdTagLoader(); - maybePreloadNextPeriodAds(); - } - - @Override - public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { - maybePreloadNextPeriodAds(); - } - - @Override - public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) { - maybePreloadNextPeriodAds(); - } - // Internal methods. private void maybeUpdateCurrentAdTagLoader() { @@ -674,7 +645,7 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { } private void maybePreloadNextPeriodAds() { - @Nullable Player player = this.player; + @Nullable Player player = ImaAdsLoader.this.player; if (player == null) { return; } @@ -708,6 +679,38 @@ public final class ImaAdsLoader implements Player.Listener, AdsLoader { nextAdTagLoader.maybePreloadAds(Util.usToMs(periodPositionUs), Util.usToMs(period.durationUs)); } + private final class PlayerListenerImpl implements Player.Listener { + + @Override + public void onTimelineChanged(Timeline timeline, @Player.TimelineChangeReason int reason) { + if (timeline.isEmpty()) { + // The player is being reset or contains no media. + return; + } + maybeUpdateCurrentAdTagLoader(); + maybePreloadNextPeriodAds(); + } + + @Override + public void onPositionDiscontinuity( + Player.PositionInfo oldPosition, + Player.PositionInfo newPosition, + @Player.DiscontinuityReason int reason) { + maybeUpdateCurrentAdTagLoader(); + maybePreloadNextPeriodAds(); + } + + @Override + public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { + maybePreloadNextPeriodAds(); + } + + @Override + public void onRepeatModeChanged(@Player.RepeatMode int repeatMode) { + maybePreloadNextPeriodAds(); + } + } + /** * Default {@link ImaUtil.ImaFactory} for non-test usage, which delegates to {@link * ImaSdkFactory}. diff --git a/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/FakeExoPlayer.java b/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/FakeExoPlayer.java index c27f353aa7..4d1fd431e7 100644 --- a/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/FakeExoPlayer.java +++ b/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/FakeExoPlayer.java @@ -15,9 +15,12 @@ */ package androidx.media3.exoplayer.ima; +import static androidx.media3.common.util.Assertions.checkState; + import android.os.Looper; import androidx.media3.common.C; import androidx.media3.common.MediaItem; +import androidx.media3.common.PlaybackException; import androidx.media3.common.Player; import androidx.media3.common.Timeline; import androidx.media3.common.TrackSelectionArray; @@ -182,6 +185,29 @@ import androidx.media3.test.utils.StubExoPlayer; } } + /** + * Sets an error on this player. + * + *

This will propagate the error to {@link Player.Listener#onPlayerError(PlaybackException)} + * and {@link Player.Listener#onPlayerErrorChanged(PlaybackException)} and will also update the + * state to {@link Player#STATE_IDLE}. + * + *

The player must be in {@link #STATE_BUFFERING} or {@link #STATE_READY}. + */ + @SuppressWarnings("deprecation") // Calling deprecated listener.onPlayerStateChanged() + public void setPlayerError(PlaybackException error) { + checkState(state == STATE_BUFFERING || state == STATE_READY); + this.state = Player.STATE_IDLE; + listeners.sendEvent( + Player.EVENT_PLAYBACK_STATE_CHANGED, + listener -> { + listener.onPlayerError(error); + listener.onPlayerErrorChanged(error); + listener.onPlayerStateChanged(playWhenReady, state); + listener.onPlaybackStateChanged(state); + }); + } + // ExoPlayer methods. Other methods are unsupported. @Override diff --git a/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/ImaAdsLoaderTest.java b/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/ImaAdsLoaderTest.java index 7ae97242c1..97778742ff 100644 --- a/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/ImaAdsLoaderTest.java +++ b/libraries/exoplayer_ima/src/test/java/androidx/media3/exoplayer/ima/ImaAdsLoaderTest.java @@ -42,7 +42,6 @@ import androidx.media3.common.AdOverlayInfo; import androidx.media3.common.AdPlaybackState; import androidx.media3.common.AdViewProvider; import androidx.media3.common.C; -import androidx.media3.common.MediaItem; import androidx.media3.common.MimeTypes; import androidx.media3.common.PlaybackException; import androidx.media3.common.Player; @@ -276,30 +275,7 @@ public final class ImaAdsLoaderTest { ExoPlaybackException anException = ExoPlaybackException.createForSource( new IOException(), PlaybackException.ERROR_CODE_IO_UNSPECIFIED); - imaAdsLoader.onPlayerErrorChanged(anException); - imaAdsLoader.onPlayerError(anException); - imaAdsLoader.onPositionDiscontinuity( - new Player.PositionInfo( - /* windowUid= */ new Object(), - /* windowIndex= */ 0, - /* mediaItem= */ MediaItem.fromUri("http://google.com/0"), - /* periodUid= */ new Object(), - /* periodIndex= */ 0, - /* positionMs= */ 10_000, - /* contentPositionMs= */ 0, - /* adGroupIndex= */ -1, - /* adIndexInAdGroup= */ -1), - new Player.PositionInfo( - /* windowUid= */ new Object(), - /* windowIndex= */ 1, - /* mediaItem= */ MediaItem.fromUri("http://google.com/1"), - /* periodUid= */ new Object(), - /* periodIndex= */ 0, - /* positionMs= */ 20_000, - /* contentPositionMs= */ 0, - /* adGroupIndex= */ -1, - /* adIndexInAdGroup= */ -1), - Player.DISCONTINUITY_REASON_SEEK); + fakePlayer.setPlayerError(anException); adEventListener.onAdEvent(getAdEvent(AdEventType.CONTENT_RESUME_REQUESTED, /* ad= */ null)); imaAdsLoader.handlePrepareError( adsMediaSource, /* adGroupIndex= */ 0, /* adIndexInAdGroup= */ 0, new IOException());