这是indexloc提供的服务,不要输入任何密码
Skip to content

CompositionPlayer.release() ANR #2539

@AradiPatrik

Description

@AradiPatrik

Version

Media3 pre-release (alpha, beta or RC not in this list)

More version details

1.8.0-alpha01

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions