diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java index 08428368ef..86cf79948c 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayer.java @@ -495,6 +495,7 @@ public interface ExoPlayer extends Player { /* package */ SeekParameters seekParameters; /* package */ long seekBackIncrementMs; /* package */ long seekForwardIncrementMs; + /* package */ long maxSeekToPreviousPositionMs; /* package */ LivePlaybackSpeedControl livePlaybackSpeedControl; /* package */ long releaseTimeoutMs; /* package */ long detachSurfaceTimeoutMs; @@ -702,6 +703,7 @@ public interface ExoPlayer extends Player { seekParameters = SeekParameters.DEFAULT; seekBackIncrementMs = C.DEFAULT_SEEK_BACK_INCREMENT_MS; seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS; + maxSeekToPreviousPositionMs = C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS; livePlaybackSpeedControl = new DefaultLivePlaybackSpeedControl.Builder().build(); clock = Clock.DEFAULT; releaseTimeoutMs = DEFAULT_RELEASE_TIMEOUT_MS; @@ -1124,6 +1126,24 @@ public interface ExoPlayer extends Player { return this; } + /** + * Sets the maximum position for which {@link #seekToPrevious()} seeks to the previous {@link + * MediaItem}. + * + * @param maxSeekToPreviousPositionMs The maximum position, in milliseconds. + * @return This builder. + * @throws IllegalArgumentException If {@code maxSeekToPreviousPositionMs} is negative. + * @throws IllegalStateException If {@link #build()} has already been called. + */ + @CanIgnoreReturnValue + @UnstableApi + public Builder setMaxSeekToPreviousPosition(long maxSeekToPreviousPositionMs) { + checkArgument(maxSeekToPreviousPositionMs >= 0L); + checkState(!buildCalled); + this.maxSeekToPreviousPositionMs = maxSeekToPreviousPositionMs; + return this; + } + /** * Sets a timeout for calls to {@link #release} and {@link #setForegroundMode}. * diff --git a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java index edcde1d4cc..fed65154a9 100644 --- a/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java +++ b/libraries/exoplayer/src/main/java/androidx/media3/exoplayer/ExoPlayerImpl.java @@ -174,6 +174,7 @@ import java.util.concurrent.TimeoutException; private final BandwidthMeter bandwidthMeter; private final long seekBackIncrementMs; private final long seekForwardIncrementMs; + private final long maxSeekToPreviousPositionMs; private final Clock clock; private final ComponentListener componentListener; private final FrameMetadataListener frameMetadataListener; @@ -286,6 +287,7 @@ import java.util.concurrent.TimeoutException; this.seekParameters = builder.seekParameters; this.seekBackIncrementMs = builder.seekBackIncrementMs; this.seekForwardIncrementMs = builder.seekForwardIncrementMs; + this.maxSeekToPreviousPositionMs = builder.maxSeekToPreviousPositionMs; this.pauseAtEndOfMediaItems = builder.pauseAtEndOfMediaItems; this.applicationLooper = builder.looper; this.clock = builder.clock; @@ -972,7 +974,7 @@ import java.util.concurrent.TimeoutException; @Override public long getMaxSeekToPreviousPosition() { verifyApplicationThread(); - return C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS; + return maxSeekToPreviousPositionMs; } @Override diff --git a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestExoPlayerBuilder.java b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestExoPlayerBuilder.java index 73bdb26ea4..79d438bee0 100644 --- a/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestExoPlayerBuilder.java +++ b/libraries/test_utils/src/main/java/androidx/media3/test/utils/TestExoPlayerBuilder.java @@ -54,6 +54,7 @@ public class TestExoPlayerBuilder { private @MonotonicNonNull Looper looper; private long seekBackIncrementMs; private long seekForwardIncrementMs; + private long maxSeekToPreviousPositionMs; private boolean deviceVolumeControlEnabled; private boolean suppressPlaybackWhenUnsuitableOutput; @Nullable private ExoPlayer.PreloadConfiguration preloadConfiguration; @@ -71,6 +72,7 @@ public class TestExoPlayerBuilder { } seekBackIncrementMs = C.DEFAULT_SEEK_BACK_INCREMENT_MS; seekForwardIncrementMs = C.DEFAULT_SEEK_FORWARD_INCREMENT_MS; + maxSeekToPreviousPositionMs = C.DEFAULT_MAX_SEEK_TO_PREVIOUS_POSITION_MS; deviceVolumeControlEnabled = false; } @@ -316,6 +318,23 @@ public class TestExoPlayerBuilder { return seekForwardIncrementMs; } + /** + * Sets the max seek to previous position, in milliseconds, to be used by the player. + * + * @param maxSeekToPreviousPositionMs The max seek to previous position to be used by the player. + * @return This builder. + */ + @CanIgnoreReturnValue + public TestExoPlayerBuilder setMaxSeekToPreviousPosition(long maxSeekToPreviousPositionMs) { + this.maxSeekToPreviousPositionMs = maxSeekToPreviousPositionMs; + return this; + } + + /** Returns the max seek to previous position used by the player. */ + public long getMaxSeekToPreviousPosition() { + return maxSeekToPreviousPositionMs; + } + /** * See {@link ExoPlayer.Builder#setSuppressPlaybackOnUnsuitableOutput(boolean)} for details. * @@ -379,6 +398,7 @@ public class TestExoPlayerBuilder { .setLooper(looper) .setSeekBackIncrementMs(seekBackIncrementMs) .setSeekForwardIncrementMs(seekForwardIncrementMs) + .setMaxSeekToPreviousPosition(maxSeekToPreviousPositionMs) .setDeviceVolumeControlEnabled(deviceVolumeControlEnabled) .setSuppressPlaybackOnUnsuitableOutput(suppressPlaybackWhenUnsuitableOutput) .experimentalSetDynamicSchedulingEnabled(dynamicSchedulingEnabled);