# TestPlayerRunHelper.PlayerRunResult

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.PlayerRunResult)

*** ** * ** ***


```
public class TestPlayerRunHelper.PlayerRunResult
```

<br />

Known direct subclasses [TestPlayerRunHelper.CompositionPlayerRunResult](https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.CompositionPlayerRunResult), [TestPlayerRunHelper.ExoPlayerRunResult](https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.ExoPlayerRunResult)

|---|---|
| `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.CompositionPlayerRunResult` | A `https://developer.android.com/reference/androidx/media3/transformer/CompositionPlayer` specific subclass of `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult`, giving access to conditions that only make sense for `https://developer.android.com/reference/androidx/media3/transformer/CompositionPlayer`. |
| `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. |

*** ** * ** ***

Intermediate type that allows callers to run the main `https://developer.android.com/reference/android/os/Looper.html` until certain conditions are met.

If an error occurs while a `untilXXX(...)` method is waiting for the condition to become true, most methods will throw that error (exceptions to this are documented on specific methods below). Use `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#ignoringNonFatalErrors()` to ignore non-fatal errors and only fail on `https://developer.android.com/reference/androidx/media3/common/Player#getPlayerError()`.

Instances of this class should only be used for a single `untilXXX()` invocation and not be re-used.

## Summary

| ### Protected fields |
|---|---|
| `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()` |

| ### Public methods |
|---|---|
| `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#ignoringNonFatalErrors()()` Returns a new instance where the `untilXXX(...)` methods ignore non-fatal errors. |
| `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. |
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#untilPlayerError()()` Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until a player 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. |
| `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult` | `https://developer.android.com/reference/androidx/media3/test/utils/robolectric/TestPlayerRunHelper.PlayerRunResult#withTimeoutMs(long)(long timeoutMs)` Returns a new instance where the `untilXXX(...)` methods use the given timeout. |

| ### Protected methods |
|---|---|
| `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. |

## Protected fields

### hasBeenUsed

```
protected boolean hasBeenUsed
```

### playBeforeWaiting

```
protected final boolean playBeforeWaiting
```

### player

```
protected final Player player
```

### throwNonFatalErrors

```
protected final boolean throwNonFatalErrors
```

### timeoutMs

```
protected final long timeoutMs
```

## Public methods

### ignoringNonFatalErrors

```
public TestPlayerRunHelper.PlayerRunResult 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)`).

### untilAdCompleted

```
public final void untilAdCompleted(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.

| Parameters |
|---|---|
| `int adGroupIndex` | The non-negative ad group index. |
| `int adIndexInAdGroup` | The non-negative ad index in the ad group. |

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/IllegalArgumentException.html` | If `adGroupIndex` or `adIndexInAdGroup` 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilAdGroupEnded

```
public final void untilAdGroupEnded(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.

| Parameters |
|---|---|
| `int adGroupIndex` | The non-negative ad group index. |

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/IllegalArgumentException.html` | If `adGroupIndex` 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilBackgroundThreadCondition

```
public void untilBackgroundThreadCondition(
    Clock clock,
    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://developer.android.com/reference/androidx/media3/common/util/Clock clock` | The `https://developer.android.com/reference/androidx/media3/common/util/Clock` to create a `https://developer.android.com/reference/androidx/media3/common/util/HandlerWrapper` from. |
| `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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilFirstFrameIsRendered

```
public void 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.

| 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilLoadingIs

```
public final void untilLoadingIs(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.

| 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilPendingCommandsAreFullyHandled

```
public void untilPendingCommandsAreFullyHandled(Clock clock, Looper 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.

Both fatal and non-fatal errors are always ignored.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/util/Clock clock` | The player's `https://developer.android.com/reference/androidx/media3/common/util/Clock`. |
| `https://developer.android.com/reference/android/os/Looper.html targetLooper` | The looper whose pending tasks to handle. |

| 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)`. |

### untilPlayWhenReadyIs

```
public final void untilPlayWhenReadyIs(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.

| 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilPlayerError

```
public PlaybackException 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/common/PlaybackException` | 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)`. |

### untilPlayingAd

```
public final void untilPlayingAd(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.

| Parameters |
|---|---|
| `int adGroupIndex` | The non-negative ad group index. |
| `int adIndexInAdGroup` | The non-negative ad index in the ad group. |

| Throws |
|---|---|
| `https://developer.android.com/reference/java/lang/IllegalArgumentException.html` | If `adGroupIndex` or `adIndexInAdGroup` 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilPlayingAdIs

```
public final void untilPlayingAdIs(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.

| 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilPositionDiscontinuityWithReason

```
public final void untilPositionDiscontinuityWithReason(
    @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.

| 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilState

```
public final void untilState(@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.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` | If a fatal 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilTimelineChanges

```
public final Timeline untilTimelineChanges()
```

Runs tasks of the main `https://developer.android.com/reference/android/os/Looper.html` until a timeline change 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### untilTimelineChangesTo

```
public final void untilTimelineChangesTo(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.

| 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.PlayerRunResult#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.PlayerRunResult#withTimeoutMs(long)`. |

### withTimeoutMs

```
public TestPlayerRunHelper.PlayerRunResult 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. |

## Protected methods

### runUntil

```
protected final void runUntil(Supplier<Boolean> predicate)
```

Runs the main `https://developer.android.com/reference/android/os/Looper.html` until `predicate` returns true or an error occurs.

| Throws |
|---|---|
| `https://developer.android.com/reference/androidx/media3/common/PlaybackException` |   |
| `https://developer.android.com/reference/java/util/concurrent/TimeoutException.html` |   |