Pass player ID to methods of LoadControl

The old methods are deprecated and are called from the new
method for backwards compatibility of custom implementations.

'DefaultLoadControl' is unchanged, but `ExoPlayerImplInternal`
already calls the new methods passing in the `PlayerId`,

PiperOrigin-RevId: 613197190
This commit is contained in:
bachinger 2024-03-06 06:44:59 -08:00 committed by Copybara-Service
parent a90a7049e8
commit a0a40871b5
10 changed files with 322 additions and 78 deletions

View file

@ -14,6 +14,8 @@
`DefaultPreloadManager` which uses `PreloadMediaSource` to preload media `DefaultPreloadManager` which uses `PreloadMediaSource` to preload media
samples of the sources into memory, and uses an integer `rankingData` samples of the sources into memory, and uses an integer `rankingData`
that indicates the index of an item on the UI. that indicates the index of an item on the UI.
* Add `PlayerId` to most methods of `LoadControl` to enable `LoadControl`
implementations to support multiple players.
* Transformer: * Transformer:
* Add `audioConversionProcess` and `videoConversionProcess` to * Add `audioConversionProcess` and `videoConversionProcess` to
`ExportResult` indicating how the respective track in the output file `ExportResult` indicating how the respective track in the output file

View file

@ -54,6 +54,7 @@ import androidx.media3.datasource.DataSource;
import androidx.media3.exoplayer.analytics.AnalyticsCollector; import androidx.media3.exoplayer.analytics.AnalyticsCollector;
import androidx.media3.exoplayer.analytics.AnalyticsListener; import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector; import androidx.media3.exoplayer.analytics.DefaultAnalyticsCollector;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.audio.AudioSink; import androidx.media3.exoplayer.audio.AudioSink;
import androidx.media3.exoplayer.audio.MediaCodecAudioRenderer; import androidx.media3.exoplayer.audio.MediaCodecAudioRenderer;
import androidx.media3.exoplayer.image.ImageOutput; import androidx.media3.exoplayer.image.ImageOutput;
@ -478,6 +479,7 @@ public interface ExoPlayer extends Player {
@Nullable /* package */ Looper playbackLooper; @Nullable /* package */ Looper playbackLooper;
/* package */ boolean buildCalled; /* package */ boolean buildCalled;
/* package */ boolean suppressPlaybackOnUnsuitableOutput; /* package */ boolean suppressPlaybackOnUnsuitableOutput;
/* package */ String playerName;
/** /**
* Creates a builder. * Creates a builder.
@ -678,6 +680,7 @@ public interface ExoPlayer extends Player {
releaseTimeoutMs = DEFAULT_RELEASE_TIMEOUT_MS; releaseTimeoutMs = DEFAULT_RELEASE_TIMEOUT_MS;
detachSurfaceTimeoutMs = DEFAULT_DETACH_SURFACE_TIMEOUT_MS; detachSurfaceTimeoutMs = DEFAULT_DETACH_SURFACE_TIMEOUT_MS;
usePlatformDiagnostics = true; usePlatformDiagnostics = true;
playerName = "";
} }
/** /**
@ -1187,6 +1190,24 @@ public interface ExoPlayer extends Player {
return this; return this;
} }
/**
* Sets the player name that is included in the {@link PlayerId} for informational purpose to
* recognize the player by its {@link PlayerId}.
*
* <p>The default is an empty string.
*
* @param playerName A name for the player in the {@link PlayerId}.
* @return This builder.
* @throws IllegalStateException If {@link #build()} has already been called.
*/
@CanIgnoreReturnValue
@UnstableApi
public Builder setName(String playerName) {
checkState(!buildCalled);
this.playerName = playerName;
return this;
}
/** /**
* Builds an {@link ExoPlayer} instance. * Builds an {@link ExoPlayer} instance.
* *

View file

@ -347,9 +347,12 @@ import java.util.concurrent.TimeoutException;
analyticsCollector.setPlayer(this.wrappingPlayer, applicationLooper); analyticsCollector.setPlayer(this.wrappingPlayer, applicationLooper);
PlayerId playerId = PlayerId playerId =
Util.SDK_INT < 31 Util.SDK_INT < 31
? new PlayerId() ? new PlayerId(builder.playerName)
: Api31.registerMediaMetricsListener( : Api31.registerMediaMetricsListener(
applicationContext, /* player= */ this, builder.usePlatformDiagnostics); applicationContext,
/* player= */ this,
builder.usePlatformDiagnostics,
builder.playerName);
internalPlayer = internalPlayer =
new ExoPlayerImplInternal( new ExoPlayerImplInternal(
renderers, renderers,
@ -3386,16 +3389,16 @@ import java.util.concurrent.TimeoutException;
@DoNotInline @DoNotInline
public static PlayerId registerMediaMetricsListener( public static PlayerId registerMediaMetricsListener(
Context context, ExoPlayerImpl player, boolean usePlatformDiagnostics) { Context context, ExoPlayerImpl player, boolean usePlatformDiagnostics, String playerName) {
@Nullable MediaMetricsListener listener = MediaMetricsListener.create(context); @Nullable MediaMetricsListener listener = MediaMetricsListener.create(context);
if (listener == null) { if (listener == null) {
Log.w(TAG, "MediaMetricsService unavailable."); Log.w(TAG, "MediaMetricsService unavailable.");
return new PlayerId(LogSessionId.LOG_SESSION_ID_NONE); return new PlayerId(LogSessionId.LOG_SESSION_ID_NONE, playerName);
} }
if (usePlatformDiagnostics) { if (usePlatformDiagnostics) {
player.addAnalyticsListener(listener); player.addAnalyticsListener(listener);
} }
return new PlayerId(listener.getLogSessionId()); return new PlayerId(listener.getLogSessionId(), playerName);
} }
} }

View file

@ -208,6 +208,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private final MediaSourceList mediaSourceList; private final MediaSourceList mediaSourceList;
private final LivePlaybackSpeedControl livePlaybackSpeedControl; private final LivePlaybackSpeedControl livePlaybackSpeedControl;
private final long releaseTimeoutMs; private final long releaseTimeoutMs;
private final PlayerId playerId;
@SuppressWarnings("unused") @SuppressWarnings("unused")
private SeekParameters seekParameters; private SeekParameters seekParameters;
@ -266,11 +267,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
this.setForegroundModeTimeoutMs = releaseTimeoutMs; this.setForegroundModeTimeoutMs = releaseTimeoutMs;
this.pauseAtEndOfWindow = pauseAtEndOfWindow; this.pauseAtEndOfWindow = pauseAtEndOfWindow;
this.clock = clock; this.clock = clock;
this.playerId = playerId;
playbackMaybeBecameStuckAtMs = C.TIME_UNSET; playbackMaybeBecameStuckAtMs = C.TIME_UNSET;
lastRebufferRealtimeMs = C.TIME_UNSET; lastRebufferRealtimeMs = C.TIME_UNSET;
backBufferDurationUs = loadControl.getBackBufferDurationUs(); backBufferDurationUs = loadControl.getBackBufferDurationUs(playerId);
retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe(); retainBackBufferFromKeyframe = loadControl.retainBackBufferFromKeyframe(playerId);
playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult); playbackInfo = PlaybackInfo.createDummy(emptyTrackSelectorResult);
playbackInfoUpdate = new PlaybackInfoUpdate(playbackInfo); playbackInfoUpdate = new PlaybackInfoUpdate(playbackInfo);
@ -772,7 +774,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* resetPosition= */ false, /* resetPosition= */ false,
/* releaseMediaSourceList= */ false, /* releaseMediaSourceList= */ false,
/* resetError= */ true); /* resetError= */ true);
loadControl.onPrepared(); loadControl.onPrepared(playerId);
setState(playbackInfo.timeline.isEmpty() ? Player.STATE_ENDED : Player.STATE_BUFFERING); setState(playbackInfo.timeline.isEmpty() ? Player.STATE_ENDED : Player.STATE_BUFFERING);
mediaSourceList.prepare(bandwidthMeter.getTransferListener()); mediaSourceList.prepare(bandwidthMeter.getTransferListener());
handler.sendEmptyMessage(MSG_DO_SOME_WORK); handler.sendEmptyMessage(MSG_DO_SOME_WORK);
@ -1473,7 +1475,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* releaseMediaSourceList= */ true, /* releaseMediaSourceList= */ true,
/* resetError= */ false); /* resetError= */ false);
playbackInfoUpdate.incrementPendingOperationAcks(acknowledgeStop ? 1 : 0); playbackInfoUpdate.incrementPendingOperationAcks(acknowledgeStop ? 1 : 0);
loadControl.onStopped(); loadControl.onStopped(playerId);
setState(Player.STATE_IDLE); setState(Player.STATE_IDLE);
} }
@ -1485,7 +1487,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
/* releaseMediaSourceList= */ true, /* releaseMediaSourceList= */ true,
/* resetError= */ false); /* resetError= */ false);
releaseRenderers(); releaseRenderers();
loadControl.onReleased(); loadControl.onReleased(playerId);
setState(Player.STATE_IDLE); setState(Player.STATE_IDLE);
} finally { } finally {
if (internalPlaybackThread != null) { if (internalPlaybackThread != null) {
@ -1938,6 +1940,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
return isBufferedToEnd return isBufferedToEnd
|| isAdPendingPreparation || isAdPendingPreparation
|| loadControl.shouldStartPlayback( || loadControl.shouldStartPlayback(
playerId,
playbackInfo.timeline, playbackInfo.timeline,
playingPeriodHolder.info.id, playingPeriodHolder.info.id,
getTotalBufferedDurationUs(), getTotalBufferedDurationUs(),
@ -2522,7 +2525,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
- loadingPeriodHolder.info.startPositionUs; - loadingPeriodHolder.info.startPositionUs;
boolean shouldContinueLoading = boolean shouldContinueLoading =
loadControl.shouldContinueLoading( loadControl.shouldContinueLoading(
playbackPositionUs, bufferedDurationUs, mediaClock.getPlaybackParameters().speed); playerId,
playbackInfo.timeline,
loadingPeriodHolder.info.id,
playbackPositionUs,
bufferedDurationUs,
mediaClock.getPlaybackParameters().speed);
if (!shouldContinueLoading if (!shouldContinueLoading
&& bufferedDurationUs < PLAYBACK_BUFFER_EMPTY_THRESHOLD_US && bufferedDurationUs < PLAYBACK_BUFFER_EMPTY_THRESHOLD_US
&& (backBufferDurationUs > 0 || retainBackBufferFromKeyframe)) { && (backBufferDurationUs > 0 || retainBackBufferFromKeyframe)) {
@ -2534,7 +2542,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
.discardBuffer(playbackInfo.positionUs, /* toKeyframe= */ false); .discardBuffer(playbackInfo.positionUs, /* toKeyframe= */ false);
shouldContinueLoading = shouldContinueLoading =
loadControl.shouldContinueLoading( loadControl.shouldContinueLoading(
playbackPositionUs, bufferedDurationUs, mediaClock.getPlaybackParameters().speed); playerId,
playbackInfo.timeline,
loadingPeriodHolder.info.id,
playbackPositionUs,
bufferedDurationUs,
mediaClock.getPlaybackParameters().speed);
} }
return shouldContinueLoading; return shouldContinueLoading;
} }
@ -2759,6 +2772,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
TrackGroupArray trackGroups, TrackGroupArray trackGroups,
TrackSelectorResult trackSelectorResult) { TrackSelectorResult trackSelectorResult) {
loadControl.onTracksSelected( loadControl.onTracksSelected(
playerId,
playbackInfo.timeline, playbackInfo.timeline,
mediaPeriodId, mediaPeriodId,
renderers, renderers,

View file

@ -19,6 +19,7 @@ import androidx.media3.common.C;
import androidx.media3.common.Timeline; import androidx.media3.common.Timeline;
import androidx.media3.common.TrackGroup; import androidx.media3.common.TrackGroup;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.source.MediaPeriod; import androidx.media3.exoplayer.source.MediaPeriod;
import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId; import androidx.media3.exoplayer.source.MediaSource.MediaPeriodId;
import androidx.media3.exoplayer.source.TrackGroupArray; import androidx.media3.exoplayer.source.TrackGroupArray;
@ -37,15 +38,31 @@ public interface LoadControl {
@Deprecated @Deprecated
MediaPeriodId EMPTY_MEDIA_PERIOD_ID = new MediaPeriodId(/* periodUid= */ new Object()); MediaPeriodId EMPTY_MEDIA_PERIOD_ID = new MediaPeriodId(/* periodUid= */ new Object());
/** Called by the player when prepared with a new source. */ /**
void onPrepared(); * Called by the player when prepared with a new source.
*
* @param playerId The {@linkplain PlayerId ID of the player} that prepared a new source.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onPrepared(PlayerId playerId) {
onPrepared();
}
/**
* @deprecated Use {@link #onPrepared(PlayerId)} instead.
*/
@Deprecated
default void onPrepared() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("onPrepared not implemented");
}
/** /**
* Called by the player when a track selection occurs. * Called by the player when a track selection occurs.
* *
* @param timeline The current {@link Timeline} in ExoPlayer. Can be {@link Timeline#EMPTY} only * @param playerId The {@linkplain PlayerId ID of the player} that selected tracks.
* when the deprecated {@link #onTracksSelected(Renderer[], TrackGroupArray, * @param timeline The current {@link Timeline} in ExoPlayer.
* ExoTrackSelection[])} was called.
* @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} for which the * @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} for which the
* selection was made. Will be {@link #EMPTY_MEDIA_PERIOD_ID} when {@code timeline} is empty. * selection was made. Will be {@link #EMPTY_MEDIA_PERIOD_ID} when {@code timeline} is empty.
* @param renderers The renderers. * @param renderers The renderers.
@ -53,6 +70,22 @@ public interface LoadControl {
* @param trackSelections The track selections that were made. * @param trackSelections The track selections that were made.
*/ */
@SuppressWarnings("deprecation") // Calling deprecated version of this method. @SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onTracksSelected(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodId,
Renderer[] renderers,
TrackGroupArray trackGroups,
ExoTrackSelection[] trackSelections) {
onTracksSelected(timeline, mediaPeriodId, renderers, trackGroups, trackSelections);
}
/**
* @deprecated Implement {@link #onTracksSelected(PlayerId, Timeline, MediaPeriodId, Renderer[],
* TrackGroupArray, ExoTrackSelection[])} instead.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
@Deprecated
default void onTracksSelected( default void onTracksSelected(
Timeline timeline, Timeline timeline,
MediaPeriodId mediaPeriodId, MediaPeriodId mediaPeriodId,
@ -63,22 +96,57 @@ public interface LoadControl {
} }
/** /**
* @deprecated Implement {@link #onTracksSelected(Timeline, MediaPeriodId, Renderer[], * @deprecated Implement {@link #onTracksSelected(PlayerId, Timeline, MediaPeriodId, Renderer[],
* TrackGroupArray, ExoTrackSelection[])} instead. * TrackGroupArray, ExoTrackSelection[])} instead.
*/ */
@SuppressWarnings("deprecation") // Intentionally referencing deprecated constant @SuppressWarnings("deprecation") // Calling deprecated version of this method.
@Deprecated @Deprecated
default void onTracksSelected( default void onTracksSelected(
Renderer[] renderers, TrackGroupArray trackGroups, ExoTrackSelection[] trackSelections) { Renderer[] renderers, TrackGroupArray trackGroups, ExoTrackSelection[] trackSelections) {
onTracksSelected( // Media3 ExoPlayer will never call this method. This default implementation provides an
Timeline.EMPTY, EMPTY_MEDIA_PERIOD_ID, renderers, trackGroups, trackSelections); // implementation to please the compiler only.
throw new IllegalStateException("onTracksSelected not implemented");
} }
/** Called by the player when stopped. */ /**
void onStopped(); * Called by the player when stopped.
*
* @param playerId The {@linkplain PlayerId ID of the player} that was stopped.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onStopped(PlayerId playerId) {
onStopped();
}
/** Called by the player when released. */ /**
void onReleased(); * @deprecated Implement {@link #onStopped(PlayerId)} instead.
*/
@Deprecated
default void onStopped() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("onStopped not implemented");
}
/**
* Called by the player when released.
*
* @param playerId The {@linkplain PlayerId ID of the player} that was released.
*/
@SuppressWarnings("deprecation") // Calling deprecated version of this method.
default void onReleased(PlayerId playerId) {
onReleased();
}
/**
* @deprecated Implement {@link #onReleased(PlayerId)} instead.
*/
@Deprecated
default void onReleased() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("onReleased not implemented");
}
/** Returns the {@link Allocator} that should be used to obtain media buffer allocations. */ /** Returns the {@link Allocator} that should be used to obtain media buffer allocations. */
Allocator getAllocator(); Allocator getAllocator();
@ -93,10 +161,25 @@ public interface LoadControl {
* <p>Note: Implementations should return a single value. Dynamic changes to the back-buffer are * <p>Note: Implementations should return a single value. Dynamic changes to the back-buffer are
* not currently supported. * not currently supported.
* *
* @param playerId The {@linkplain PlayerId ID of the player} that requests the back buffer
* duration.
* @return The duration of media to retain in the buffer prior to the current playback position, * @return The duration of media to retain in the buffer prior to the current playback position,
* in microseconds. * in microseconds.
*/ */
long getBackBufferDurationUs(); @SuppressWarnings("deprecation") // Calling deprecated version of this method.
default long getBackBufferDurationUs(PlayerId playerId) {
return getBackBufferDurationUs();
}
/**
* @deprecated Implements {@link #getBackBufferDurationUs(PlayerId)} instead.
*/
@Deprecated
default long getBackBufferDurationUs() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("getBackBufferDurationUs not implemented");
}
/** /**
* Returns whether media should be retained from the keyframe before the current playback position * Returns whether media should be retained from the keyframe before the current playback position
@ -111,17 +194,36 @@ public interface LoadControl {
* <p>Note: Implementations should return a single value. Dynamic changes to the back-buffer are * <p>Note: Implementations should return a single value. Dynamic changes to the back-buffer are
* not currently supported. * not currently supported.
* *
* @param playerId The {@linkplain PlayerId ID of the player} that requests whether to retain the
* back buffer from key frame.
* @return Whether media should be retained from the keyframe before the current playback position * @return Whether media should be retained from the keyframe before the current playback position
* minus {@link #getBackBufferDurationUs()}, rather than any sample before or at that * minus {@link #getBackBufferDurationUs()}, rather than any sample before or at that
* position. * position.
*/ */
boolean retainBackBufferFromKeyframe(); @SuppressWarnings("deprecation") // Calling deprecated version of this method.
default boolean retainBackBufferFromKeyframe(PlayerId playerId) {
return retainBackBufferFromKeyframe();
}
/**
* @deprecated Implements {@link #retainBackBufferFromKeyframe(PlayerId)} instead.
*/
@Deprecated
default boolean retainBackBufferFromKeyframe() {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("retainBackBufferFromKeyframe not implemented");
}
/** /**
* Called by the player to determine whether it should continue to load the source. If this method * Called by the player to determine whether it should continue to load the source. If this method
* returns true, the {@link MediaPeriod} identified in the most recent {@link #onTracksSelected} * returns true, the {@link MediaPeriod} identified in the most recent {@link #onTracksSelected}
* call will continue being loaded. * call will continue being loaded.
* *
* @param playerId The {@linkplain PlayerId ID of the player} that wants to continue loading.
* @param timeline The current {@link Timeline} in ExoPlayer.
* @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} that is
* currently loading.
* @param playbackPositionUs The current playback position in microseconds, relative to the start * @param playbackPositionUs The current playback position in microseconds, relative to the start
* of the {@link Timeline.Period period} that will continue to be loaded if this method * of the {@link Timeline.Period period} that will continue to be loaded if this method
* returns {@code true}. If playback of this period has not yet started, the value will be * returns {@code true}. If playback of this period has not yet started, the value will be
@ -131,8 +233,28 @@ public interface LoadControl {
* @param playbackSpeed The current factor by which playback is sped up. * @param playbackSpeed The current factor by which playback is sped up.
* @return Whether the loading should continue. * @return Whether the loading should continue.
*/ */
boolean shouldContinueLoading( @SuppressWarnings("deprecation") // Calling deprecated version of this method.
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed); default boolean shouldContinueLoading(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodId,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return shouldContinueLoading(playbackPositionUs, bufferedDurationUs, playbackSpeed);
}
/**
* @deprecated Implement {@link #shouldContinueLoading(PlayerId, Timeline, MediaPeriodId, long,
* long, float)} instead.
*/
@Deprecated
default boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("shouldContinueLoading not implemented");
}
/** /**
* Called repeatedly by the player when it's loading the source, has yet to start playback, and * Called repeatedly by the player when it's loading the source, has yet to start playback, and
@ -140,6 +262,7 @@ public interface LoadControl {
* determines whether playback is actually started. The load control may opt to return {@code * determines whether playback is actually started. The load control may opt to return {@code
* false} until some condition has been met (e.g. a certain amount of media is buffered). * false} until some condition has been met (e.g. a certain amount of media is buffered).
* *
* @param playerId The {@linkplain PlayerId ID of the player} that wants to start playback.
* @param timeline The current {@link Timeline} in ExoPlayer. Can be {@link Timeline#EMPTY} only * @param timeline The current {@link Timeline} in ExoPlayer. Can be {@link Timeline#EMPTY} only
* when the deprecated {@link #shouldStartPlayback(long, float, boolean, long)} was called. * when the deprecated {@link #shouldStartPlayback(long, float, boolean, long)} was called.
* @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} for which * @param mediaPeriodId Identifies (in the current timeline) the {@link MediaPeriod} for which
@ -156,29 +279,48 @@ public interface LoadControl {
*/ */
@SuppressWarnings("deprecation") // Calling deprecated version of this method. @SuppressWarnings("deprecation") // Calling deprecated version of this method.
default boolean shouldStartPlayback( default boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline, Timeline timeline,
MediaPeriodId mediaPeriodId, MediaPeriodId mediaPeriodId,
long bufferedDurationUs, long bufferedDurationUs,
float playbackSpeed, float playbackSpeed,
boolean rebuffering, boolean rebuffering,
long targetLiveOffsetUs) { long targetLiveOffsetUs) {
return shouldStartPlayback(bufferedDurationUs, playbackSpeed, rebuffering, targetLiveOffsetUs);
}
/**
* @deprecated Implement {@link #shouldStartPlayback(Timeline, MediaPeriodId, long, float,
* boolean, long)} instead.
*/
@SuppressWarnings("deprecation") // Intentionally referencing deprecated constant
@Deprecated
default boolean shouldStartPlayback(
long bufferedDurationUs, float playbackSpeed, boolean rebuffering, long targetLiveOffsetUs) {
return shouldStartPlayback( return shouldStartPlayback(
Timeline.EMPTY, timeline,
EMPTY_MEDIA_PERIOD_ID, mediaPeriodId,
bufferedDurationUs, bufferedDurationUs,
playbackSpeed, playbackSpeed,
rebuffering, rebuffering,
targetLiveOffsetUs); targetLiveOffsetUs);
} }
/**
* @deprecated Implement {@link #shouldStartPlayback(PlayerId, Timeline, MediaPeriodId, long,
* float, boolean, long)} instead.
*/
@Deprecated
default boolean shouldStartPlayback(
Timeline timeline,
MediaPeriodId mediaPeriodId,
long bufferedDurationUs,
float playbackSpeed,
boolean rebuffering,
long targetLiveOffsetUs) {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("shouldStartPlayback not implemented");
}
/**
* @deprecated Implement {@link #shouldStartPlayback(PlayerId, Timeline, MediaPeriodId, long,
* float, boolean, long)} instead.
*/
@Deprecated
default boolean shouldStartPlayback(
long bufferedDurationUs, float playbackSpeed, boolean rebuffering, long targetLiveOffsetUs) {
// Media3 ExoPlayer will never call this method. This default implementation provides an
// implementation to please the compiler only.
throw new IllegalStateException("shouldStartPlayback not implemented");
}
} }

View file

@ -23,6 +23,8 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.common.util.Util; import androidx.media3.common.util.Util;
import androidx.media3.exoplayer.ExoPlayer.Builder;
import java.util.Objects;
/** Identifier for a player instance. */ /** Identifier for a player instance. */
@UnstableApi @UnstableApi
@ -32,28 +34,69 @@ public final class PlayerId {
* A player identifier with unset default values that can be used as a placeholder or for testing. * A player identifier with unset default values that can be used as a placeholder or for testing.
*/ */
public static final PlayerId UNSET = public static final PlayerId UNSET =
Util.SDK_INT < 31 ? new PlayerId() : new PlayerId(LogSessionIdApi31.UNSET); Util.SDK_INT < 31
? new PlayerId(/* playerName= */ "")
: new PlayerId(LogSessionIdApi31.UNSET, /* playerName= */ "");
/**
* A name to identify the player. Use {@link Builder#setName(String)} to set the name, otherwise
* an empty string is used as the default.
*/
public final String name;
@Nullable private final LogSessionIdApi31 logSessionIdApi31; @Nullable private final LogSessionIdApi31 logSessionIdApi31;
/** Creates an instance for API &lt; 31. */ /**
public PlayerId() { * An object used for equals/hashCode below API 31 or when the MediaMetricsService is unavailable.
*/
@Nullable private final Object equalityToken;
/**
* Creates an instance for API &lt; 31.
*
* @param playerName The name of the player, for informational purpose only.
*/
public PlayerId(String playerName) {
checkState(Util.SDK_INT < 31); checkState(Util.SDK_INT < 31);
this.name = playerName;
this.logSessionIdApi31 = null; this.logSessionIdApi31 = null;
equalityToken = new Object();
} }
/** /**
* Creates an instance for API &ge; 31. * Creates an instance for API &ge; 31.
* *
* @param logSessionId The {@link LogSessionId} used for this player. * @param logSessionId The {@link LogSessionId} used for this player.
* @param playerName The name of the player, for informational purpose only.
*/ */
@RequiresApi(31) @RequiresApi(31)
public PlayerId(LogSessionId logSessionId) { public PlayerId(LogSessionId logSessionId, String playerName) {
this(new LogSessionIdApi31(logSessionId)); this(new LogSessionIdApi31(logSessionId), playerName);
} }
private PlayerId(LogSessionIdApi31 logSessionIdApi31) { private PlayerId(LogSessionIdApi31 logSessionIdApi31, String playerName) {
this.logSessionIdApi31 = logSessionIdApi31; this.logSessionIdApi31 = logSessionIdApi31;
this.name = playerName;
equalityToken = new Object();
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (!(o instanceof PlayerId)) {
return false;
}
PlayerId playerId = (PlayerId) o;
return Objects.equals(name, playerId.name)
&& Objects.equals(logSessionIdApi31, playerId.logSessionIdApi31)
&& Objects.equals(equalityToken, playerId.equalityToken);
}
@Override
public int hashCode() {
return Objects.hash(name, logSessionIdApi31, equalityToken);
} }
/** Returns the {@link LogSessionId} for this player instance. */ /** Returns the {@link LogSessionId} for this player instance. */

View file

@ -137,6 +137,7 @@ import androidx.media3.common.util.Util;
import androidx.media3.datasource.TransferListener; import androidx.media3.datasource.TransferListener;
import androidx.media3.decoder.DecoderInputBuffer; import androidx.media3.decoder.DecoderInputBuffer;
import androidx.media3.exoplayer.analytics.AnalyticsListener; import androidx.media3.exoplayer.analytics.AnalyticsListener;
import androidx.media3.exoplayer.analytics.PlayerId;
import androidx.media3.exoplayer.audio.AudioRendererEventListener; import androidx.media3.exoplayer.audio.AudioRendererEventListener;
import androidx.media3.exoplayer.drm.DrmSessionEventListener; import androidx.media3.exoplayer.drm.DrmSessionEventListener;
import androidx.media3.exoplayer.drm.DrmSessionManager; import androidx.media3.exoplayer.drm.DrmSessionManager;
@ -5931,12 +5932,20 @@ public final class ExoPlayerTest {
new DefaultLoadControl() { new DefaultLoadControl() {
@Override @Override
public boolean shouldContinueLoading( public boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) { PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return false; return false;
} }
@Override @Override
public boolean shouldStartPlayback( public boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long bufferedDurationUs, long bufferedDurationUs,
float playbackSpeed, float playbackSpeed,
boolean rebuffering, boolean rebuffering,
@ -5978,12 +5987,20 @@ public final class ExoPlayerTest {
new DefaultLoadControl() { new DefaultLoadControl() {
@Override @Override
public boolean shouldContinueLoading( public boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) { PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return bufferedDurationUs < maxBufferUs; return bufferedDurationUs < maxBufferUs;
} }
@Override @Override
public boolean shouldStartPlayback( public boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long bufferedDurationUs, long bufferedDurationUs,
float playbackSpeed, float playbackSpeed,
boolean rebuffering, boolean rebuffering,
@ -6058,12 +6075,20 @@ public final class ExoPlayerTest {
new DefaultLoadControl() { new DefaultLoadControl() {
@Override @Override
public boolean shouldContinueLoading( public boolean shouldContinueLoading(
long playbackPositionUs, long bufferedDurationUs, float playbackSpeed) { PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long playbackPositionUs,
long bufferedDurationUs,
float playbackSpeed) {
return true; return true;
} }
@Override @Override
public boolean shouldStartPlayback( public boolean shouldStartPlayback(
PlayerId playerId,
Timeline timeline,
MediaPeriodId mediaPeriodid,
long bufferedDurationUs, long bufferedDurationUs,
float playbackSpeed, float playbackSpeed,
boolean rebuffering, boolean rebuffering,
@ -12947,7 +12972,7 @@ public final class ExoPlayerTest {
spy( spy(
new DefaultLoadControl() { new DefaultLoadControl() {
@Override @Override
public void onReleased() { public void onReleased(PlayerId playerId) {
// Emulate a failure during player release. // Emulate a failure during player release.
throw new RuntimeException(); throw new RuntimeException();
} }
@ -12958,13 +12983,13 @@ public final class ExoPlayerTest {
.build(); .build();
player.addListener(listener); player.addListener(listener);
// Ensure load control has not thrown the exception yet. // Ensure load control has not thrown the exception yet.
verify(loadControl, never()).onReleased(); verify(loadControl, never()).onReleased(any());
player.release(); player.release();
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
// Verify load control threw the exception. // Verify load control threw the exception.
verify(loadControl).onReleased(); verify(loadControl).onReleased(any());
verify(listener, never()).onPlayerError(any()); verify(listener, never()).onPlayerError(any());
} }

View file

@ -62,7 +62,6 @@ import org.mockito.Mock;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class DefaultPreloadManagerTest { public class DefaultPreloadManagerTest {
@Mock private TargetPreloadStatusControl<Integer> mockTargetPreloadStatusControl; @Mock private TargetPreloadStatusControl<Integer> mockTargetPreloadStatusControl;
private PlayerId playerId;
private TrackSelector trackSelector; private TrackSelector trackSelector;
private Allocator allocator; private Allocator allocator;
private BandwidthMeter bandwidthMeter; private BandwidthMeter bandwidthMeter;
@ -70,7 +69,6 @@ public class DefaultPreloadManagerTest {
@Before @Before
public void setUp() { public void setUp() {
playerId = new PlayerId();
trackSelector = new DefaultTrackSelector(ApplicationProvider.getApplicationContext()); trackSelector = new DefaultTrackSelector(ApplicationProvider.getApplicationContext());
allocator = new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE); allocator = new DefaultAllocator(/* trimOnReset= */ true, C.DEFAULT_BUFFER_SEGMENT_SIZE);
bandwidthMeter = bandwidthMeter =
@ -252,7 +250,7 @@ public class DefaultPreloadManagerTest {
PreloadMediaSource preloadMediaSource2 = PreloadMediaSource preloadMediaSource2 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem2); (PreloadMediaSource) preloadManager.getMediaSource(mediaItem2);
preloadMediaSource2.prepareSource( preloadMediaSource2.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadManager.setCurrentPlayingIndex(2); preloadManager.setCurrentPlayingIndex(2);
preloadManager.invalidate(); preloadManager.invalidate();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
@ -303,7 +301,7 @@ public class DefaultPreloadManagerTest {
PreloadMediaSource preloadMediaSource0 = PreloadMediaSource preloadMediaSource0 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem0); (PreloadMediaSource) preloadManager.getMediaSource(mediaItem0);
preloadMediaSource0.prepareSource( preloadMediaSource0.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadManager.setCurrentPlayingIndex(0); preloadManager.setCurrentPlayingIndex(0);
preloadManager.invalidate(); preloadManager.invalidate();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
@ -314,7 +312,7 @@ public class DefaultPreloadManagerTest {
PreloadMediaSource preloadMediaSource2 = PreloadMediaSource preloadMediaSource2 =
(PreloadMediaSource) preloadManager.getMediaSource(mediaItem2); (PreloadMediaSource) preloadManager.getMediaSource(mediaItem2);
preloadMediaSource2.prepareSource( preloadMediaSource2.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadManager.setCurrentPlayingIndex(2); preloadManager.setCurrentPlayingIndex(2);
preloadManager.invalidate(); preloadManager.invalidate();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();

View file

@ -63,7 +63,6 @@ import org.robolectric.shadows.ShadowLooper;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class PreloadAndPlaybackCoordinationTest { public class PreloadAndPlaybackCoordinationTest {
private final PlayerId playerId;
private final BandwidthMeter bandwidthMeter; private final BandwidthMeter bandwidthMeter;
private final PreloadMediaSource preloadMediaSource; private final PreloadMediaSource preloadMediaSource;
private final FakeMediaSource wrappedMediaSource; private final FakeMediaSource wrappedMediaSource;
@ -76,7 +75,6 @@ public class PreloadAndPlaybackCoordinationTest {
private final AtomicReference<MediaPeriod> preloadMediaPeriodReference; private final AtomicReference<MediaPeriod> preloadMediaPeriodReference;
public PreloadAndPlaybackCoordinationTest() { public PreloadAndPlaybackCoordinationTest() {
playerId = new PlayerId();
Context context = ApplicationProvider.getApplicationContext(); Context context = ApplicationProvider.getApplicationContext();
bandwidthMeter = new DefaultBandwidthMeter.Builder(context).build(); bandwidthMeter = new DefaultBandwidthMeter.Builder(context).build();
FakeMediaSourceFactory mediaSourceFactory = new FakeMediaSourceFactory(); FakeMediaSourceFactory mediaSourceFactory = new FakeMediaSourceFactory();
@ -165,7 +163,7 @@ public class PreloadAndPlaybackCoordinationTest {
@Test @Test
public void playbackWithoutPreload_reusableForPreloadAfterRelease() { public void playbackWithoutPreload_reusableForPreloadAfterRelease() {
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId); playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(0);
@ -188,7 +186,7 @@ public class PreloadAndPlaybackCoordinationTest {
@Test @Test
public void playbackBeforePreload_reusableForPreloadAfterRelease() { public void playbackBeforePreload_reusableForPreloadAfterRelease() {
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId); playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadMediaSource.preload(/* startPositionUs= */ 0L); preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
@ -216,7 +214,7 @@ public class PreloadAndPlaybackCoordinationTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L); preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId); playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
wrappedMediaSource.setAllowPreparation(true); wrappedMediaSource.setAllowPreparation(true);
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
@ -245,7 +243,7 @@ public class PreloadAndPlaybackCoordinationTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L); preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId); playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
FakeMediaPeriod lastCreatedActiveMediaPeriod = FakeMediaPeriod lastCreatedActiveMediaPeriod =
(FakeMediaPeriod) wrappedMediaSource.getLastCreatedActiveMediaPeriod(); (FakeMediaPeriod) wrappedMediaSource.getLastCreatedActiveMediaPeriod();
lastCreatedActiveMediaPeriod.setPreparationComplete(); lastCreatedActiveMediaPeriod.setPreparationComplete();
@ -274,7 +272,7 @@ public class PreloadAndPlaybackCoordinationTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L); preloadMediaSource.preload(/* startPositionUs= */ 0L);
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), playerId); playbackMediaSourceCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
ShadowLooper.idleMainLooper(); ShadowLooper.idleMainLooper();
assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1); assertThat(preloadControlOnSourceInfoRefreshedCalledCounter.get()).isEqualTo(1);

View file

@ -80,7 +80,6 @@ public final class PreloadMediaSourceTest {
private Allocator allocator; private Allocator allocator;
private BandwidthMeter bandwidthMeter; private BandwidthMeter bandwidthMeter;
private RenderersFactory renderersFactory; private RenderersFactory renderersFactory;
private PlayerId playerId;
@Before @Before
public void setUp() { public void setUp() {
@ -97,7 +96,6 @@ public final class PreloadMediaSourceTest {
SystemClock.DEFAULT.createHandler(handler.getLooper(), /* callback= */ null), SystemClock.DEFAULT.createHandler(handler.getLooper(), /* callback= */ null),
audioListener) audioListener)
}; };
playerId = new PlayerId();
} }
@Test @Test
@ -326,7 +324,7 @@ public final class PreloadMediaSourceTest {
} }
}; };
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.preload(/* startPositionUs= */ 0L); preloadMediaSource.preload(/* startPositionUs= */ 0L);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
@ -391,7 +389,7 @@ public final class PreloadMediaSourceTest {
} }
}; };
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
wrappedMediaSource.setAllowPreparation(true); wrappedMediaSource.setAllowPreparation(true);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
@ -453,7 +451,7 @@ public final class PreloadMediaSourceTest {
} }
}; };
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
assertThat(onTimelineRefreshedCalled.get()).isTrue(); assertThat(onTimelineRefreshedCalled.get()).isTrue();
assertThat(onPreparedCalled.get()).isTrue(); assertThat(onPreparedCalled.get()).isTrue();
@ -551,7 +549,7 @@ public final class PreloadMediaSourceTest {
} }
}; };
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
Pair<Object, Long> periodPosition = Pair<Object, Long> periodPosition =
externalCallerSourceInfoTimelineReference externalCallerSourceInfoTimelineReference
.get() .get()
@ -658,7 +656,7 @@ public final class PreloadMediaSourceTest {
} }
}; };
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
// Create a period from different position. // Create a period from different position.
Pair<Object, Long> periodPosition = Pair<Object, Long> periodPosition =
externalCallerSourceInfoTimelineReference externalCallerSourceInfoTimelineReference
@ -740,7 +738,7 @@ public final class PreloadMediaSourceTest {
} }
}; };
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.releaseSource(externalCaller); preloadMediaSource.releaseSource(externalCaller);
@ -819,7 +817,7 @@ public final class PreloadMediaSourceTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L); preloadMediaSource.preload(/* startPositionUs= */ 0L);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadMediaSource.releaseSource(externalCaller); preloadMediaSource.releaseSource(externalCaller);
assertThat(onTimelineRefreshedCalled.get()).isTrue(); assertThat(onTimelineRefreshedCalled.get()).isTrue();
@ -903,9 +901,9 @@ public final class PreloadMediaSourceTest {
} }
}; };
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller1, bandwidthMeter.getTransferListener(), playerId); externalCaller1, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller2, bandwidthMeter.getTransferListener(), playerId); externalCaller2, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
// Only releaseSource by externalCaller1. // Only releaseSource by externalCaller1.
preloadMediaSource.releaseSource(externalCaller1); preloadMediaSource.releaseSource(externalCaller1);
@ -1054,7 +1052,7 @@ public final class PreloadMediaSourceTest {
preloadMediaSource.preload(/* startPositionUs= */ 0L); preloadMediaSource.preload(/* startPositionUs= */ 0L);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.prepareSource( preloadMediaSource.prepareSource(
externalCaller, bandwidthMeter.getTransferListener(), playerId); externalCaller, bandwidthMeter.getTransferListener(), PlayerId.UNSET);
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();
preloadMediaSource.releasePreloadMediaSource(); preloadMediaSource.releasePreloadMediaSource();
shadowOf(Looper.getMainLooper()).idle(); shadowOf(Looper.getMainLooper()).idle();