# TestPlayerRunHelper.ExoPlayerRunResult

Artifact: [androidx.media3:media3-test-utils-robolectric](https://developer.android.com/jetpack/androidx/releases/media3) [View Source](https://cs.android.com/search?q=file:androidx/media3/test/utils/robolectric/TestPlayerRunHelper.java+class:androidx.media3.test.utils.robolectric.TestPlayerRunHelper.ExoPlayerRunResult)

*** ** * ** ***


```
public final class TestPlayerRunHelper.ExoPlayerRunResult extends TestPlayerRunHelper.PlayerRunResult
```

<br />

|---|---|---|
| [java.lang.Object](https://developer.android.com/reference/java/lang/Object.html) |||
| ↳ | [androidx.media3.test.utils.robolectric.TestPlayerRunHelper.PlayerRunResult](https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult) ||
|   | ↳ | [androidx.media3.test.utils.robolectric.TestPlayerRunHelper.ExoPlayerRunResult](https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult) |

*** ** * ** ***

An `https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer` specific subclass of `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult`, giving access to conditions that only make sense for the `https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer` interface.

## Summary

| ### Public methods |
|---|---|
| `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()()` Returns a new instance where the `untilXXX(...)` methods ignore non-fatal errors. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilAdPositionAtLeast(int,int,long)( int adGroupIndex, int adIndexInAdGroup, long adPositionMs )` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the specified ad is playing and `https://developer.android.com/reference/androidx/media3/common/Player#getCurrentPosition()` reaches at least `adPositionMs`, or an error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilBackgroundThreadCondition(com.google.common.base.Supplier<java.lang.Boolean>)( https://guava.dev/releases/snapshot-android/api/docs/com/google/common/base/Supplier.html<https://developer.android.com/reference/java/lang/Boolean.html> backgroundThreadCondition )` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the specified condition becomes true independent of a message on the main `https://developer.android.com/reference/android/os/Looper.html`. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilClockAdvancementMs(long)(long durationMs)` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the player's `https://developer.android.com/reference/androidx/media3/common/util/Clock#elapsedRealtime()` has advanced by at least `durationMs`, or an error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilFullyBuffered()()` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the player has fully buffered its entire playlist and stopped reporting `https://developer.android.com/reference/androidx/media3/common/Player#isLoading()`. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilMediaItemIndex(int)(int mediaItemIndex)` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getCurrentMediaItemIndex()` equals the specified index or an error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPendingCommandsAreFullyHandled()()` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the player completely handled all previously issued commands on the internal playback thread. |
| `https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlaybackException` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPlayerError()()` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until a player error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPosition(int,long)(int mediaItemIndex, long positionMs)` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the internal playback thread reaches the specified position or an error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPositionAtLeast(long)(long positionMs)` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getContentPosition()` reaches at least the specified position in the current media item, or an error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPositionAtLeast(int,long)(int mediaItemIndex, long positionMs)` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getCurrentMediaItemIndex()` equals the specified index and `https://developer.android.com/reference/androidx/media3/common/Player#getContentPosition()` reaches at least the specified position, or an error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilSleepingForOffloadBecomes(boolean)(boolean expectedSleepingForOffload)` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer#isSleepingForOffload()` matches the expected value, or an error occurs. |
| `void` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilStartOfMediaItem(int)(int mediaItemIndex)` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the internal playback thread reaches the start of the specified media item or a playback error occurs. |
| `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)(long timeoutMs)` Returns a new instance where the `untilXXX(...)` methods use the given timeout. |

### Inherited fields

From [androidx.media3.test.utils.robolectric.TestPlayerRunHelper.PlayerRunResult](https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult) `boolean` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#hasBeenUsed()` `final boolean` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#playBeforeWaiting()` `final https://developer.android.com/reference/androidx/media3/common/Player` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#player()` `final boolean` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#throwNonFatalErrors()` `final long` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#timeoutMs()`

### Inherited methods

From [androidx.media3.test.utils.robolectric.TestPlayerRunHelper.PlayerRunResult](https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult) `final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#runUntil(com.google.common.base.Supplier<java.lang.Boolean>)(https://guava.dev/releases/snapshot-android/api/docs/com/google/common/base/Supplier.html<https://developer.android.com/reference/java/lang/Boolean.html> predicate)`

Runs the main `https://developer.android.com/reference/android/os/Looper.html` until `predicate` returns true or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilAdCompleted(int,int)(int adGroupIndex, int adIndexInAdGroup)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the specified ad finishes playing and transitions with `https://developer.android.com/reference/androidx/media3/common/Player#DISCONTINUITY_REASON_AUTO_TRANSITION()`, or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilAdGroupEnded(int)(int adGroupIndex)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until playback exits the specified `adGroupIndex` back to content (`newPosition.adGroupIndex == C.INDEX_UNSET`), or an error occurs.
`void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilBackgroundThreadCondition(androidx.media3.common.util.Clock,com.google.common.base.Supplier<java.lang.Boolean>)(
https://developer.android.com/reference/androidx/media3/common/util/Clock clock,
https://guava.dev/releases/snapshot-android/api/docs/com/google/common/base/Supplier.html<https://developer.android.com/reference/java/lang/Boolean.html> backgroundThreadCondition
)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the specified condition becomes true independent of a message on the main `https://developer.android.com/reference/android/os/Looper.html`.
`void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilFirstFrameIsRendered()()`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player.Listener#onRenderedFirstFrame()` is called or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilLoadingIs(boolean)(boolean expectedIsLoading)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#isLoading()` matches the expected value or an error occurs.
`void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilPendingCommandsAreFullyHandled(androidx.media3.common.util.Clock,android.os.Looper)(https://developer.android.com/reference/androidx/media3/common/util/Clock clock, https://developer.android.com/reference/android/os/Looper.html targetLooper)`

Runs tasks of the `https://developer.android.com/reference/android/os/Looper.html#getMainLooper()` until all pending tasks in `targetLooper` have been handled and have propagated any updates to the main looper.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilPlayWhenReadyIs(boolean)(boolean expectedPlayWhenReady)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getPlayWhenReady()` matches the expected value or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilPlayingAd(int,int)(int adGroupIndex, int adIndexInAdGroup)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#isPlayingAd()` is true for the specified `adGroupIndex` and `adIndexInAdGroup`, or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilPlayingAdIs(boolean)(boolean expectedIsPlayingAd)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#isPlayingAd()` ()} matches the expected value or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilPositionDiscontinuityWithReason(int)(
@https://developer.android.com/reference/androidx/media3/common/Player.DiscontinuityReason int expectedReason
)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player.Listener#onPositionDiscontinuity(androidx.media3.common.Player.PositionInfo,androidx.media3.common.Player.PositionInfo,int)` is called with the specified `https://developer.android.com/reference/androidx/media3/common/Player.DiscontinuityReason` or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilState(int)(@https://developer.android.com/reference/androidx/media3/common/Player.State int expectedState)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getPlaybackState()` matches the expected state or an error occurs.
`final https://developer.android.com/reference/androidx/media3/common/Timeline` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilTimelineChanges()()`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until a timeline change or an error occurs.
`final void` `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilTimelineChangesTo(androidx.media3.common.Timeline)(https://developer.android.com/reference/androidx/media3/common/Timeline expectedTimeline)`

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getCurrentTimeline()` matches the expected timeline or an error occurs.

## Public methods

### ignoringNonFatalErrors

```
public TestPlayerRunHelper.ExoPlayerRunResult ignoringNonFatalErrors()
```

Returns a new instance where the `untilXXX(...)` methods ignore non-fatal errors.

A fatal error is defined as an error that is passed to `https://developer.android.com/reference/androidx/media3/common/Player.Listener#onPlayerError(androidx.media3.common.PlaybackException)` and results in the player transitioning to `https://developer.android.com/reference/androidx/media3/common/Player#STATE_IDLE()`. A non-fatal error is defined as an error that is passed to any other callback (e.g. `https://developer.android.com/reference/androidx/media3/exoplayer/analytics/AnalyticsListener#onLoadError(androidx.media3.exoplayer.analytics.AnalyticsListener.EventTime,androidx.media3.exoplayer.source.LoadEventInfo,androidx.media3.exoplayer.source.MediaLoadData,java.io.IOException,boolean)`).

### untilAdPositionAtLeast

```
public void untilAdPositionAtLeast(
    int adGroupIndex,
    int adIndexInAdGroup,
    long adPositionMs
)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the specified ad is playing and `https://developer.android.com/reference/androidx/media3/common/Player#getCurrentPosition()` reaches at least `adPositionMs`, or an error occurs.

| Parameters |
|---|---|
| `int adGroupIndex` | The non-negative ad group index. |
| `int adIndexInAdGroup` | The non-negative ad index in the ad group. |
| `long adPositionMs` | The non-negative target ad position in milliseconds. |

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/IllegalArgumentException.html` | If `adGroupIndex`, `adIndexInAdGroup`, or ` adPositionMs` is negative. |
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilBackgroundThreadCondition

```
public void untilBackgroundThreadCondition(
    Supplier<Boolean> backgroundThreadCondition
)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the specified condition becomes true independent of a message on the main `https://developer.android.com/reference/android/os/Looper.html`.

This method is useful for cases where the condition may change outside of a main `https://developer.android.com/reference/android/os/Looper.html` message, for example because it's checking a volatile variable or shared synchronized state that is updated on a background thread, or because checking the condition itself may cause it to become true.

This method ensures the condition is checked within artificially created main `https://developer.android.com/reference/android/os/Looper.html` messages. When using a `https://developer.android.com/reference/androidx/media3/test/utils/FakeClock`, this guarantees the remainder of the test method is not executed in parallel with other background thread messages.

| Parameters |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/base/Supplier.html<https://developer.android.com/reference/java/lang/Boolean.html> backgroundThreadCondition` | The condition to wait for. |

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilClockAdvancementMs

```
public void untilClockAdvancementMs(long durationMs)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the player's `https://developer.android.com/reference/androidx/media3/common/util/Clock#elapsedRealtime()` has advanced by at least `durationMs`, or an error occurs.

The clock is advanced by letting the main `https://developer.android.com/reference/android/os/Looper.html` process messages, so the player's `https://developer.android.com/reference/androidx/media3/common/util/Clock` must advance on its own when messages are due. This is the case for `https://developer.android.com/reference/androidx/media3/common/util/Clock#DEFAULT()` under Robolectric and for an `https://developer.android.com/reference/androidx/media3/test/utils/FakeClock.Builder#setIsAutoAdvancing(boolean)``https://developer.android.com/reference/androidx/media3/test/utils/FakeClock` with any `https://developer.android.com/reference/androidx/media3/test/utils/FakeClock.Builder#setMaxAutoAdvancingTimeDiffMs(long)`. A non-auto-advancing clock does not progress and the call times out.

| Parameters |
|---|---|
| `long durationMs` | The non-negative duration in milliseconds by which to advance the clock. |

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/IllegalArgumentException.html` | If `durationMs` is negative. |
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilFullyBuffered

```
public void untilFullyBuffered()
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the player has fully buffered its entire playlist and stopped reporting `https://developer.android.com/reference/androidx/media3/common/Player#isLoading()`.

Note that this method won't succeed if the player is configured with a `https://developer.android.com/reference/androidx/media3/exoplayer/LoadControl` that prevents loading the playlist fully before playback resumes.

If a `https://developer.android.com/reference/androidx/media3/common/Player.RepeatMode` setting results in an endless playlist, this method only waits until all items have been buffered at least once.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilMediaItemIndex

```
public void untilMediaItemIndex(int mediaItemIndex)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getCurrentMediaItemIndex()` equals the specified index or an error occurs.

Use `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilStartOfMediaItem(int)` instead if the test needs to advance the player until the internal playback thread reaches the start of the media item exactly.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilPendingCommandsAreFullyHandled

```
public void untilPendingCommandsAreFullyHandled()
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the player completely handled all previously issued commands on the internal playback thread.

Both fatal and non-fatal errors are always ignored.

| Throws |
|---|---|
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilPlayerError

```
public ExoPlaybackException untilPlayerError()
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until a player error occurs.

Non-fatal errors are always ignored.

| Returns |
|---|---|
| `https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlaybackException` | The raised `https://developer.android.com/reference/androidx/media3/common/PlaybackException`. |

| Throws |
|---|---|
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#withTimeoutMs(long)`. |

### untilPosition

```
public void untilPosition(int mediaItemIndex, long positionMs)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the internal playback thread reaches the specified position or an error occurs.

Use `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPositionAtLeast(long)` instead if the test needs to advance the player until the publicly visible position reaches a specified value.

The playback thread is automatically blocked from making further progress after reaching this position and will only be unblocked by other `run()/play().untilXXX(...)` method chains, custom `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#runMainLooperUntil(com.google.common.base.Supplier<java.lang.Boolean>)` conditions, or an explicit `https://developer.android.com/reference/androidx/media3/test/utils/ThreadTestUtil#unblockThreadsWaitingForProgressOnCurrentLooper()` on the main thread.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilPositionAtLeast

```
public void untilPositionAtLeast(long positionMs)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getContentPosition()` reaches at least the specified position in the current media item, or an error occurs.

Use `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPosition(int,long)` instead if the test needs to advance the player until the internal playback thread reaches a specific position exactly.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilPositionAtLeast

```
public void untilPositionAtLeast(int mediaItemIndex, long positionMs)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/common/Player#getCurrentMediaItemIndex()` equals the specified index and `https://developer.android.com/reference/androidx/media3/common/Player#getContentPosition()` reaches at least the specified position, or an error occurs.

Use `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilPosition(int,long)` instead if the test needs to advance the player until the internal playback thread reaches a specific position exactly.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilSleepingForOffloadBecomes

```
public void untilSleepingForOffloadBecomes(boolean expectedSleepingForOffload)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until `https://developer.android.com/reference/androidx/media3/exoplayer/ExoPlayer#isSleepingForOffload()` matches the expected value, or an error occurs.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### untilStartOfMediaItem

```
public void untilStartOfMediaItem(int mediaItemIndex)
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until the internal playback thread reaches the start of the specified media item or a playback error occurs.

Use `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#untilMediaItemIndex(int)` instead if the test needs to advance the player until the publicly visible media item index reaches a specified value.

The playback thread is automatically blocked from making further progress after reaching the media item and will only be unblocked by other `run()/play().untilXXX(...)` method chains, custom `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#runMainLooperUntil(com.google.common.base.Supplier<java.lang.Boolean>)` conditions, or an explicit `https://developer.android.com/reference/androidx/media3/test/utils/ThreadTestUtil#unblockThreadsWaitingForProgressOnCurrentLooper()` on the main thread.

| Parameters |
|---|---|
| `int mediaItemIndex` | The index of the media item. |

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a playback error occurs. |
| `https://developer.android.com/reference/java/lang/IllegalStateException.html` | If non-fatal playback errors occur, and aren't `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#ignoringNonFatalErrors()` (the non-fatal exceptions will be attached with `https://developer.android.com/reference/java/lang/Throwable.html#addSuppressed(java.lang.Throwable)`). |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` | If the timeout is exceeded. The timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()` by default, or a specific value if this instance is created via `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult#withTimeoutMs(long)`. |

### withTimeoutMs

```
public TestPlayerRunHelper.ExoPlayerRunResult withTimeoutMs(long timeoutMs)
```

Returns a new instance where the `untilXXX(...)` methods use the given timeout.

If not set, the default timeout is `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/RobolectricUtil#DEFAULT_TIMEOUT_MS()`.

| Parameters |
|---|---|
| `long timeoutMs` | The timeout in milliseconds. |