androidx / androidx/media

AudioCapabilitiesReceiver invokes audio capability listener on a looper-less OEM thread

Open
#3,386 4 comments 0 reactions 1 assignee View on GitHub

@icbaker is already working on this.

Since Aug 21, 2026.

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

Description

Version

Media3 1.7.1 (same as 1.6.1)

More version details

Media3 1.7.1

Devices that reproduce the issue
  • Jio STB devices running Android 10 or 11.
  • SkyworthDigital devices running Android 10 or 11.

Both onAudioDevicesAdded() and onAudioDevicesRemoved() appear in the crash reports.

Devices that do not reproduce the issue

We do not have a controlled negative-device test. No other device families have confirmed reports.

Reproducible in the demo app?

No

Reproduction steps

Reported production flow on both Jio STB and SkyworthDigital devices:

  1. Start or resume video playback.
  2. While playback is starting or active, connect, reconnect, wake, switch, or
    renegotiate the HDMI/audio route.
  3. Observe the crash.

Deterministic unit-test reproduction:

  1. Create an AudioCapabilitiesReceiver using a dedicated playback
    HandlerThread with a prepared Looper.
  2. Capture the registered AudioDeviceCallback.
  3. Invoke onAudioDevicesAdded() from a plain thread named
    AudioMonitorHdmiThread without calling Looper.prepare().
  4. Repeat with onAudioDevicesRemoved().
  5. Observe that the callback reaches the listener on the foreign thread.

The test uses a real playback HandlerThread and a plain callback thread with
no Looper. It does not require an affected device, HDMI cable, or media file.

Expected result

Capability evaluation, state changes, and listener delivery should run on the
handler/Looper captured by AudioCapabilitiesReceiver, regardless of the
callback thread used by the framework or OEM.

No exception is thrown.

Actual result

AudioCapabilitiesReceiverexecutes the callback body directly on the OEM callback thread. When the capabilities change, the listener is synchronously called from that thread.Looper.myLooper()isnull, while the audio sink's playback Looper is main`, causing the process to crash:

Fatal Exception: java.lang.IllegalStateException:
Current looper (null) is not the playback looper (main)
    at androidx.media3.exoplayer.audio.DefaultAudioSink.onAudioCapabilitiesChanged(DefaultAudioSink.java:1600)
    at androidx.media3.exoplayer.audio.AudioCapabilitiesReceiver.onNewAudioCapabilities(AudioCapabilitiesReceiver.java:199)
    at androidx.media3.exoplayer.audio.AudioCapabilitiesReceiver$AudioDeviceCallbackV23.onAudioDevicesAdded(AudioCapabilitiesReceiver.java:246)
    at android.media.AudioManager$AudioMonitorHdmiThread.run(AudioManager.java:5692)

The removal path has the same failure:

Fatal Exception: java.lang.IllegalStateException:
Current looper (null) is not the playback looper (main)
    at androidx.media3.exoplayer.audio.DefaultAudioSink.onAudioCapabilitiesChanged(DefaultAudioSink.java:1600)
    at androidx.media3.exoplayer.audio.AudioCapabilitiesReceiver.onNewAudioCapabilities(AudioCapabilitiesReceiver.java:199)
    at androidx.media3.exoplayer.audio.AudioCapabilitiesReceiver$AudioDeviceCallbackV23.onAudioDevicesRemoved(AudioCapabilitiesReceiver.java:255)
    at android.media.AudioManager$AudioMonitorHdmiThread.run(AudioManager.java:5047)

The primary local assertion against the unmodified implementation is:

expected: ExoPlayer:Playback
but was : AudioMonitorHdmiThread

Media

Not applicable. The crash is caused by audio-device callback threading and does not depend on the media being played.

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.