|
122 | 122 | import androidx.media3.common.Timeline; |
123 | 123 | import androidx.media3.common.Timeline.Window; |
124 | 124 | import androidx.media3.common.TrackGroup; |
| 125 | +import androidx.media3.common.TrackSelectionParameters; |
125 | 126 | import androidx.media3.common.TrackSelectionParameters.AudioOffloadPreferences; |
126 | 127 | import androidx.media3.common.Tracks; |
127 | 128 | import androidx.media3.common.VideoSize; |
@@ -14101,6 +14102,53 @@ protected void onStreamChanged( |
14101 | 14102 | .isSameInstanceAs(mediaItem2); |
14102 | 14103 | } |
14103 | 14104 |
|
| 14105 | + @Test |
| 14106 | + public void seekToZeroAndTrackSelection_withNonZeroDefaultPosition_startsPlaybackAtZero() |
| 14107 | + throws Exception { |
| 14108 | + // Create a timeline with a non-zero default position. It's important to use a |
| 14109 | + // windowOffsetInFirstPeriodUs of zero to ensure that our later manual seek to zero could be |
| 14110 | + // mistaken for the initial placeholder start position of zero |
| 14111 | + // (see https://github.com/google/ExoPlayer/issues/9347). |
| 14112 | + Timeline timeline = |
| 14113 | + new FakeTimeline( |
| 14114 | + new TimelineWindowDefinition( |
| 14115 | + /* periodCount= */ 1, |
| 14116 | + /* id= */ new Object(), |
| 14117 | + /* isSeekable= */ true, |
| 14118 | + /* isDynamic= */ true, |
| 14119 | + /* isLive= */ true, |
| 14120 | + /* isPlaceholder= */ false, |
| 14121 | + /* durationUs= */ 10_000_000, |
| 14122 | + /* defaultPositionUs= */ 9_000_000, |
| 14123 | + /* windowOffsetInFirstPeriodUs= */ 0, |
| 14124 | + /* adPlaybackState= */ AdPlaybackState.NONE)); |
| 14125 | + FakeMediaSource mediaSource = |
| 14126 | + new FakeMediaSource( |
| 14127 | + timeline, ExoPlayerTestRunner.VIDEO_FORMAT, ExoPlayerTestRunner.AUDIO_FORMAT); |
| 14128 | + // Make sure the player has to use its placeholder values initially. |
| 14129 | + mediaSource.setAllowPreparation(false); |
| 14130 | + ExoPlayer player = new TestExoPlayerBuilder(context).build(); |
| 14131 | + player.setMediaSource(mediaSource); |
| 14132 | + player.prepare(); |
| 14133 | + runUntilPendingCommandsAreFullyHandled(player); |
| 14134 | + mediaSource.setAllowPreparation(true); |
| 14135 | + runUntilPlaybackState(player, Player.STATE_READY); |
| 14136 | + long positionAfterPrepare = player.getCurrentPosition(); |
| 14137 | + |
| 14138 | + // Manually seek back to zero and force to reselect tracks. |
| 14139 | + player.seekTo(0); |
| 14140 | + player.setTrackSelectionParameters( |
| 14141 | + new TrackSelectionParameters.Builder(context) |
| 14142 | + .setTrackTypeDisabled(C.TRACK_TYPE_AUDIO, /* disabled= */ true) |
| 14143 | + .build()); |
| 14144 | + runUntilPendingCommandsAreFullyHandled(player); |
| 14145 | + long positionAfterSeek = player.getContentPosition(); |
| 14146 | + player.release(); |
| 14147 | + |
| 14148 | + assertThat(positionAfterPrepare).isEqualTo(9000); |
| 14149 | + assertThat(positionAfterSeek).isEqualTo(0); |
| 14150 | + } |
| 14151 | + |
14104 | 14152 | // Internal methods. |
14105 | 14153 |
|
14106 | 14154 | private void addWatchAsSystemFeature() { |
|
0 commit comments