CompositionPlayer.release() ANR
Version
Media3 pre-release (alpha, beta or RC not in this list)
More version details
Devices that reproduce the issue
Galaxy S24 Galaxy S24 ultra Galaxy S23 V40
Devices that do not reproduce the issue
Reproducible in the demo app?
Not tested
Reproduction steps
I use the code below for my composable showing a composition inside a composition player. From time-to-time player.release will block indefinitely and this will cause ANR. This happens when the composition changes and I need to create a new player and dispose the previous player.
@SuppressLint("RestrictedApi")
@OptIn(UnstableApi::class)
@Composable
fun CompositionPlayerView(
state: CompositionPlayerViewState,
modifier: Modifier,
) {
val context = LocalContext.current
val player = remember(state.composition) {
CompositionPlayer.Builder(context)
.build()
.apply {
setComposition(state.composition)
prepare()
playWhenReady = true
}
}
val lifecycleOwner = context as LifecycleOwner
ComposableLifecycle(lifecycleOwner) { _, event ->
when (event) {
Lifecycle.Event.ON_PAUSE -> {
player.pause()
}
else -> Unit
}
}
PlayerSurface(
player = player,
modifier = modifier.clickable {
if (player.isPlaying) {
player.pause()
} else {
player.play()
}
},
)
DisposableEffect(player) {
onDispose {
player.pause()
player.stop()
player.release()
}
}
}
I traced the issue and found that the ANR happens because conditionVariable.block() blocks indefinitely
public void release() {
checkState(!released);
// Set released to true now to silence any pending listener callback.
released = true;
ConditionVariable conditionVariable = new ConditionVariable();
handler.obtainMessage(MSG_RELEASE, conditionVariable).sendToTarget();
clock.onThreadBlocked();
try {
conditionVariable.block(); // this is the exact point where we get blocked indefinetely
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
}
Expected result
compositionPlayer.release() shouldn't cause ANR
Actual result
compositionPlayer.release() causes ANR
Media
doesn't matter
Bug Report
- [ ] You will email the zip file produced by
adb bugreportto [email protected] after filing this issue.
Do you use custom effects in the Composition? Can you check if it's DefaultVideoFrameProcessor.release() blocked indefinitely? (Sorry I cannot reproduce it locally)
Do you use custom effects in the
Composition? Can you check if it'sDefaultVideoFrameProcessor.release()blocked indefinitely? (Sorry I cannot reproduce it locally)
Sorry I forgot to link the stack trace from the ANR you can find it below. I do use effects: Presentation.createForWIdthAndHight and my own MatrixTransformation for scaling and translation. I also use clipping configuration on the videos and images.
main (waiting):tid=1 systid=11866
at java.lang.Object.wait(Native method)
at java.lang.Object.wait(Object.java:405)
at java.lang.Object.wait(Object.java:543)
at androidx.media3.common.util.ConditionVariable.block(ConditionVariable.java:86)
at androidx.media3.transformer.CompositionPlayerInternal.release(CompositionPlayerInternal.java:149)
at androidx.media3.transformer.CompositionPlayer.handleRelease(CompositionPlayer.java:599)
at androidx.media3.common.SimpleBasePlayer.release(SimpleBasePlayer.java:2608)
at com.cardinalblue.onbeat.ui.screens.maineditor.player.MultiMediaItemExoPlayerKt$CompositionPlayerView$lambda$13$lambda$12$$inlined$onDispose$1.dispose(Effects.kt:71)
at androidx.compose.runtime.DisposableEffectImpl.onForgotten(Effects.kt:87)
at androidx.compose.runtime.internal.RememberEventDispatcher.dispatchRememberObservers(RememberEventDispatcher.kt:158)
at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:1044)
at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:1067)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:684)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Recomposer.kt:591)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:39)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.java:108)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.java:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1749)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1760)
at android.view.Choreographer.doCallbacks(Choreographer.java:1216)
at android.view.Choreographer.doFrame(Choreographer.java:1132)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1707)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:257)
at android.os.Looper.loop(Looper.java:342)
at android.app.ActivityThread.main(ActivityThread.java:9638)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:619)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:929)
It seems like it's not DefaultVideoFrameProcessor.release() but CompositionPlayerInternal.release()
Hi @AradiPatrik , Are you using the new Compose PlayerSurface together with CompositionPlayer? If this is the case, unfortunately, we have not integrated and tested CompositionPlayer fully with Compose yet. Please use playerView if you want to use CompositionPlayer.
Hi @droid-girl! Thanks for the support. Yes I'm using PlayerSurface. I will change the implementation to use PlayerView and report back whether the ANRs disappeared from crashlytics as a result or not.
@droid-girl Transitioning to PlayerView had this error: https://github.com/androidx/media/issues/2554
I will keep this issue open for checking if the ANR issue is solved after using PlayerView with the workaround mentioned in the issue above.
@droid-girl I can still reproduce the ANR changing PlayerSurface to PlayerView. I was able to recover additional stack trace (this is the error before the ANR)
playerFailed [eventTime=8.57, mediaPos=11.54, window=0, period=7, errorCode=ERROR_CODE_TIMEOUT
androidx.media3.exoplayer.ExoPlaybackException: Unexpected runtime error
at androidx.media3.exoplayer.ExoPlayerImpl.lambda$release$6(Unknown Source:8)
at androidx.media3.exoplayer.ExoPlayerImpl.C(Unknown Source:0)
at androidx.media3.exoplayer.x.invoke(Unknown Source:2)
at androidx.media3.common.util.ListenerSet$ListenerHolder.invoke(Unknown Source:17)
at androidx.media3.common.util.ListenerSet.lambda$queueEvent$0(Unknown Source:16)
at androidx.media3.common.util.ListenerSet.a(Unknown Source:0)
at Z3.e.run(Unknown Source:129)
at androidx.media3.common.util.ListenerSet.flushEvents(Unknown Source:67)
at androidx.media3.common.util.ListenerSet.sendEvent(Unknown Source:3)
at androidx.media3.exoplayer.ExoPlayerImpl.release(Unknown Source:104)
at androidx.media3.transformer.CompositionPlayer.handleRelease(Unknown Source:39)
at androidx.media3.common.SimpleBasePlayer.release(Unknown Source:14)
at A.Q.a(Unknown Source:131)
at S.F.b(Unknown Source:4)
at a0.h.d(Unknown Source:49)
at S.w.e(Unknown Source:60)
at S.w.d(Unknown Source:5)
at S.w0.invoke(Unknown Source:190)
at E0.e0.doFrame(Unknown Source:6)
at E0.c0.doFrame(Unknown Source:47)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1687)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1698)
at android.view.Choreographer.doCallbacks(Choreographer.java:1153)
at android.view.Choreographer.doFrame(Choreographer.java:1069)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1646)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:230)
at android.os.Looper.loop(Looper.java:319)
at android.app.ActivityThread.main(ActivityThread.java:8919)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Caused by: androidx.media3.exoplayer.ExoTimeoutException: Player release timed out.
at androidx.media3.exoplayer.ExoPlayerImpl.lambda$release$6(Unknown Source:3)
at androidx.media3.exoplayer.ExoPlayerImpl.C(Unknown Source:0)
at androidx.media3.exoplayer.x.invoke(Unknown Source:2)
at androidx.media3.common.util.ListenerSet$ListenerHolder.invoke(Unknown Source:17)
at androidx.media3.common.util.ListenerSet.lambda$queueEvent$0(Unknown Source:16)
at androidx.media3.common.util.ListenerSet.a(Unknown Source:0)
at Z3.e.run(Unknown Source:129)
at androidx.media3.common.util.ListenerSet.flushEvents(Unknown Source:67)
at androidx.media3.common.util.ListenerSet.sendEvent(Unknown Source:3)
at androidx.media3.exoplayer.ExoPlayerImpl.release(Unknown Source:104)
at androidx.media3.transformer.CompositionPlayer.handleRelease(Unknown Source:39)
at androidx.media3.common.SimpleBasePlayer.release(Unknown Source:14)
at A.Q.a(Unknown Source:131)
at S.F.b(Unknown Source:4)
at a0.h.d(Unknown Source:49)
at S.w.e(Unknown Source:60)
at S.w.d(Unknown Source:5)
at S.w0.invoke(Unknown Source:190)
at E0.e0.doFrame(Unknown Source:6)
at E0.c0.doFrame(Unknown Source:47)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1687)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1698)
at android.view.Choreographer.doCallbacks(Choreographer.java:1153)
at android.view.Choreographer.doFrame(Choreographer.java:1069)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1646)
at android.os.Handler.handleCallback(Handler.java:958)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:230)
at android.os.Looper.loop(Looper.java:319)
at android.app.ActivityThread.main(ActivityThread.java:8919)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
Can you verify if this Player release timed out error still reproduces on the main branch?
The error you're seeing may be fixed by some of our recent changes
@ychaparov This only shows up in production (≈2% ANRs) and is hard to reproduce locally, so I’ll test the next release and report back.
After updating to 1.8.0-beta01 can no longer reproduce (or see it in crashlytics). Thanks 🙏