MediaLibraryService enters tight create/destroy loop when Android Auto binds while no playback is ongoing
@marcbaechinger is already working on this.
Since Apr 7, 2026.
- 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
This started happening recently 2-3 weeks ago and was only noticed because some of our users were rate limited due to excessive api calls which are being done when service is created to generate a queue from last listening session.
Devices that reproduce the issue
- Tested on Samsung Galaxy Z Flip5 (Android 16) and Pixel 5 (Android 14)
- Android Auto connected via Desktop Head Unit (DHU)
- Also reproducible with a simple instrumentation test using
bindService/unbindService
Devices that do not reproduce the issue
No response
Reproducible in the demo app?
Not tested
Reproduction steps
When Android Auto connects to a phone, it discovers media apps by binding to their MediaLibraryService using the legacy android.media.browse.MediaBrowserService action. If no playback is ongoing, the following loop occurs at ~30-35ms per cycle:
onCreate → onBind → onGetSession → onConnect → onPostConnect → onUnbind → onDestroy → (repeat)
No onStartCommand is ever called — the service is started purely by binding (BIND_AUTO_CREATE). When the external client unbinds, the service has zero remaining clients and isPlaybackOngoing is false, so Android destroys it. The external client (Android Auto) detects the service disappeared and rebinds immediately, restarting the cycle.
This loop runs indefinitely at ~28 cycles/second. Each cycle allocates a new ExoPlayer, MediaSession, and runs the full onCreate initialization. In production, this leads to:
- Resource exhaustion: leaked BroadcastReceivers/ContentObservers crash the app with "too many broadcast receivers registered"
- Backend overload: any network calls triggered during
onCreate/initializeBoundServicesfire every ~35ms, overwhelming APIs with HTTP 429 responses
Minimal reproduction (no car needed)
The following instrumentation test simulates exactly what Android Auto does — bind via the legacy action, then unbind:
@HiltAndroidTest // or however your service DI is set up
@RunWith(AndroidJUnit4::class)
class MediaServiceBindLoopTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@Before
fun setup() { hiltRule.inject() }
@Test
fun reproduceBindUnbindLoop() {
val context = InstrumentationRegistry.getInstrumentation().targetContext
val bindIntent = Intent("android.media.browse.MediaBrowserService").apply {
component = ComponentName(context, YourMediaLibraryService::class.java)
}
for (i in 1..300) {
val connection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {}
override fun onServiceDisconnected(name: ComponentName?) {}
}
if (context.bindService(bindIntent, connection, Context.BIND_AUTO_CREATE)) {
Thread.sleep(40) // Simulates AA's quick probe timing
context.unbindService(connection)
}
Thread.sleep(10)
}
}
}
Sadly I couldn't reproduce this loop with Desktop Head unit or physical AA device
Logs from production crash (sanitized)
From a Crashlytics session showing the loop. All timestamps are within the same second — 28 full cycles captured in the ring buffer:
13:33:27 MEDIA_SERVICE | onCreate
13:33:27 MEDIA_SERVICE | onBind | intent = Intent { act=android.media.browse.MediaBrowserService }
13:33:27 MEDIA_SERVICE | onGetSession | package = android.media.session.MediaController, uid = -1
13:33:27 MEDIA_SERVICE | onConnect | sessionPlayer = ForwardingPlayer@49f1214, controller = ControllerInfo {pkg=com.example.app, uid=10411}
13:33:27 MEDIA_SERVICE | onPostConnect
13:33:27 MEDIA_SERVICE | onUnbind | intent = Intent { act=android.media.browse.MediaBrowserService }
13:33:27 MEDIA_SERVICE | onDestroy
13:33:27 PlayerQueueController | unbind player: ForwardingPlayer@49f1214
13:33:27 -- cycle repeats immediately --
13:33:27 MEDIA_SERVICE | onCreate
13:33:27 MEDIA_SERVICE | onBind | intent = Intent { act=android.media.browse.MediaBrowserService }
13:33:27 MEDIA_SERVICE | onGetSession | package = android.media.session.MediaController, uid = -1
13:33:27 MEDIA_SERVICE | onConnect | sessionPlayer = ForwardingPlayer@8081986, controller = ControllerInfo {pkg=com.example.app, uid=10411}
13:33:27 MEDIA_SERVICE | onPostConnect
13:33:27 MEDIA_SERVICE | onUnbind | intent = Intent { act=android.media.browse.MediaBrowserService }
13:33:27 MEDIA_SERVICE | onDestroy
13:33:27 PlayerQueueController | unbind player: ForwardingPlayer@8081986
13:33:27 -- cycle repeats immediately --
13:33:27 MEDIA_SERVICE | onCreate
13:33:27 MEDIA_SERVICE | onBind | intent = Intent { act=android.media.browse.MediaBrowserService }
13:33:27 MEDIA_SERVICE | onGetSession | package = android.media.session.MediaController, uid = -1
13:33:27 MEDIA_SERVICE | onConnect | sessionPlayer = ForwardingPlayer@a52d2e6, controller = ControllerInfo {pkg=com.example.app, uid=10411}
13:33:27 MEDIA_SERVICE | onPostConnect
13:33:27 MEDIA_SERVICE | onUnbind | intent = Intent { act=android.media.browse.MediaBrowserService }
13:33:27 MEDIA_SERVICE | onDestroy
13:33:27 PlayerQueueController | unbind player: ForwardingPlayer@a52d2e6
Key observations:
- No
onStartCommandin any cycle — this is a bind-only start onGetSessionuid = -1 — the platform probe, not a real clientonConnectcontroller is the app's own compat controller (created internally by Media3 when a legacy MediaBrowserService bind arrives) — not an external MediaController- New player instance every cycle (different object hashes:
@49f1214,@8081986,@a52d2e6) - All within the same second — ~35ms per full cycle
Expected result
When an external client binds and quickly unbinds while no playback is ongoing, the service should not enter a tight create/destroy loop
Actual result
Service ends in tight create/destroy loop when connecting with AA which leads to crash due to too many broadcast receivers
Fatal Exception: java.lang.IllegalStateException: Too many receivers, total of 1000, registered for pid: 3226, callerPackage: com.example.app
Top 10 actions:
android.media.AUDIO_BECOMING_NOISY: 990 receivers
Media
Not applicable
Bug Report
- You will email the zip file produced by
adb bugreportto android-media-github@google.com after filing this issue.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.