androidx / androidx/media

java.lang.ArrayIndexOutOfBoundsException: length=1; index=1 at androidx.media3.common.AdPlaybackState.getAdGroup(AdPlaybackState.java:832)

Open
#3,308 5 comments 0 reactions 1 assignee View on GitHub

@marcbaechinger is already working on this.

Since Jul 1, 2026.

bug
Dominant language
Java
Stars
3k
Forks
955
Avg merge
12d 14h
Merged PRs (30d)
2

Description

Version

Media3 1.10.1

More version details

Using ExoPlayer with ImaServerSideAdInsertionMediaSource for Google DAI linear live streams

https://github.com/androidx/media/issues/3037

Devices that reproduce the issue

Android TV devices and Set-Top Boxes (e.g., Chromecast with Google TV, Xiaomi Mi Box, Android TV Emulators running API 30+).

Devices that do not reproduce the issue

None identified yet. Appears to be a race condition related to asynchronous layout/timeline timing rather than specific hardware decoders.

Reproducible in the demo app?

No

Reproduction steps
  1. Set up an ExoPlayer instance using ImaServerSideAdInsertionMediaSource to play a linear live stream with Google DAI.
  2. Start playback successfully. The player initially loads and plays the Preroll ad pod without issues.
  3. Leave the live stream playing continuously for a period of time.
  4. After a while, when the live stream fetches a dynamic multi-period background update (e.g., transitioning or updating subsequent ad periods/midrolls) while simultaneously handling a dense volume of tracking metadata from the EventStream, a race condition occurs and the player crashes on the main thread.
Expected result

The player should handle dynamic timeline and period structure transitions safely during continuous live playback. If an asynchronous ad group update arrives from the IMA SDK, the internal state should validate boundaries or safely drop/defer the update instead of breaking layout arrays.

Actual result
An ArrayIndexOutOfBoundsException is thrown inside AdPlaybackState.getAdGroup 

FATAL EXCEPTION: main
PID: 14758
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
at androidx.media3.common.AdPlaybackState.getAdGroup(AdPlaybackState.java:832)
at androidx.media3.exoplayer.source.ads.ServerSideAdInsertionMediaSource.setAdPlaybackStates(ServerSideAdInsertionMediaSource.java:176)
at androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.invalidateServerSideAdInsertionAdPlaybackState(ImaServerSideAdInsertionMediaSource.java:834)
at androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.setContentTimeline(ImaServerSideAdInsertionMediaSource.java:808)
at androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource.access$2900(ImaServerSideAdInsertionMediaSource.java:114)
at androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource$ComponentListener.lambda$onAdPlaybackStateUpdateRequested$0$androidx-media3-exoplayer-ima-ImaServerSideAdInsertionMediaSource$ComponentListener(ImaServerSideAdInsertionMediaSource.java:1083)
at androidx.media3.exoplayer.ima.ImaServerSideAdInsertionMediaSource$ComponentListener$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
at android.os.Handler.handleCallback(Handler.java:995)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loopOnce(Looper.java:248)
at android.os.Looper.loop(Looper.java:338)
at android.app.ActivityThread.main(ActivityThread.java:9067)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

  /** Returns the specified {@link AdGroup}. */
  public AdGroup getAdGroup(@IntRange(from = 0) int adGroupIndex) {
    return adGroupIndex < removedAdGroupCount
        ? REMOVED_AD_GROUP
        : adGroups[adGroupIndex - removedAdGroupCount];
  }

Media

Not applicable. The issue depends on the asynchronous timing of dynamic ad pod updates via Google DAI and is linked to the core state-handling bug discussed in issue #3037.

However, instead of trying to replicate the exact live DAI manifest timing, this issue can be easily resolved by adding a defensive check in the framework source code where the crash happens.

In androidx.media3.common.AdPlaybackState(or the equivalent ExoPlayer class), thegetAdGroup method currently looks like this:

/** Returns the specified {@link AdGroup}. */
public AdGroup getAdGroup(@IntRange(from = 0) int adGroupIndex) {
  return adGroupIndex < removedAdGroupCount
      ? REMOVED_AD_GROUP
      : adGroups[adGroupIndex - removedAdGroupCount];
}

Since asynchronous background updates from the IMA SDK can race ahead of the internal timeline/period allocations, adGroupIndex - removedAdGroupCountoccasionally exceeds the bounds of theadGroupsarray, triggering theArrayIndexOutOfBoundsException.

Proposed Fix:
Please add an array bounds check inside this method to safely handle or log the out-of-bounds index instead of crashing the main thread, for example:

Java
/** Returns the specified {@link AdGroup}. */
public AdGroup getAdGroup(@IntRange(from = 0) int adGroupIndex) {
  if (adGroupIndex < removedAdGroupCount) {
      return REMOVED_AD_GROUP;
  }
  int targetIndex = adGroupIndex - removedAdGroupCount;
  if (targetIndex >= adGroups.length) {

      return new AdGroup(/* timeUs= */ 0); 
  }
  return adGroups[targetIndex];
}
Bug Report
  • You will email the zip file produced by adb bugreport to android-media-github@google.com after filing this issue.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.