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/initializeBoundServices fire 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
onStartCommand in any cycle — this is a bind-only start
onGetSession uid = -1 — the platform probe, not a real client
onConnect controller 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
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
bindService/unbindServiceDevices 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
MediaLibraryServiceusing the legacyandroid.media.browse.MediaBrowserServiceaction. If no playback is ongoing, the following loop occurs at ~30-35ms per cycle:No
onStartCommandis ever called — the service is started purely by binding (BIND_AUTO_CREATE). When the external client unbinds, the service has zero remaining clients andisPlaybackOngoingisfalse, 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
onCreateinitialization. In production, this leads to:onCreate/initializeBoundServicesfire every ~35ms, overwhelming APIs with HTTP 429 responsesMinimal reproduction (no car needed)
The following instrumentation test simulates exactly what Android Auto does — bind via the legacy action, then unbind:
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:
Key observations:
onStartCommandin any cycle — this is a bind-only startonGetSessionuid = -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@49f1214,@8081986,@a52d2e6)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
Media
Not applicable
Bug Report
adb bugreportto android-media-github@google.com after filing this issue.