Understanding preemption

Preemption is an optional policy that you can apply to an audio type. It determines whether the audio stream is suspended when its volume is ducked to zero.

The volume can be ducked to zero either because of the ducking policy of a single audio type or the culmulative effect of the ducking policies of multiple higher-priority audio types, same-priority audio types, or both (see Understanding the mix policy when using multiple audio types with the same priority).

You use the audio policy configuration file preemptable key to specify whether an audio stream can be preempted.

For example, to stop playing music when a voice call is received, in the audio policy configuration file:

If an audio stream is ducked to zero and the preemption key for the audio type that applies to that stream is not specified or set to false, the stream stays in the RUNNING state (SND_PCM_STATUS_RUNNING) while it's muted.

Preemption puts the audio stream into the SUSPENDED (SND_PCM_STATUS_SUSPENDED) state. In some cases, you can use an API call to move out of the SUSPENDED state. For more information, see Using APIs to move out of the suspended state.

Using APIs to move out of the suspended state

When an audio stream is preempted, it moves to the SUSPENDED state (SND_PCM_STATUS_SUSPENDED), which has two modes: soft-suspended and hard-suspended.

The mode determines what happens when you call an API that attempts to transition the stream to the RUNNING mode (for example, snd_pcm_*_resume() or snd_pcm_*_go()).

soft suspended
Occurs when your audio type is preempted by an audio type of the same priority. If you call an API that transitions the audio stream to the RUNNING state, the suspended audio stream immediately moves from the SUSPENDED to the RUNNING state and preempts any other streams of the same priority.
hard suspended
Occurs when your audio type is preempted by a higher priority audio type. Calling an API that transitions the audio stream to the RUNNING state has no effect while the audio stream is suspended. When the preemption ends, the audio stream moves to the RUNNING state and preempts any other streams of the same priority.

You can use the ducking_state member of snd_pcm_channel_status_t to determine whether a channel is soft or hard suspended.

When an audio stream is suspended and you call snd_pcm_*_pause, the stream remains in the SUSPENDED state until audio management clears the SUSPENDED state, and then moves to the PAUSED state.

Manually ducking APIs and preemption

If an audio stream is in the PREPARED state (call snd_pcm_*_prepare()), you can use the snd_pcm_channel_audio_ducking() function to make audio management apply ducking polices to an audio stream as if it was RUNNING. This call also enables any preemption policy that applies. (See Understanding audio ducking and snd_pcm_channel_audio_ducking().)

Manual ducking remains active until you either use snd_pcm_channel_audio_ducking() to cancel it or reset the parameters using snd_pcm_plugin_params(). However, if the stream transitions out of the PREPARE state (for example, to READY), preemption ends but ducking of same- and lower-priority streams continues.

Making the preemption appear transient

You can't explicitly move an audio stream to or out of the SUSPENDED (SND_PCM_STATUS_SUSPENDED) state, but you can define the behavior of an audio stream when the suspension ends.

The transient key is set for the interrupting audio stream but configures the behavior of a preempted stream when preemption ends. It makes the interruption appear to be either short-lived (transient) or permanent. When a higher- or same-priority stream with transient enabled begins, the lower priority stream is suspended. When the interrupting stream stops, the lower-priority stream automatically resumes playing, which makes the interruption appear short-lived. An interrupting stream with transient disabled also suspends a lower priority steam from playing, but when the interrupting stream stops, the lower-priority stream moves to the PAUSED state. The interruption is permanent until snd_pcm_*_resume() is called.

When preemptable is true for its audio type, one of the following transitions occurs for an audio stream when preemption is lifted (no longer ducked to zero):
  • If transient is false, the stream moves from the SUSPENDED state to the PAUSED state (SND_PCM_STATUS_PAUSED) when ducking ends. It requires snd_pcm_*_resume() to move back to the RUNNING (SND_PCM_STATUS_RUNNING) state.

    This move to the PAUSED state only happens if a single higher-priority stream ducks the stream to 0. If cumulative ducking sets the volume to 0, the behavior is the same as when transient is true (see Understanding how multiple ducking levels cumulate).

  • If transient is true the stream moves from the SUSPENDED (SND_PCM_STATUS_SUSPENDED) state back the state it was in before it was preempted.

When preemptable is true:suspend, the audio stream being preempted transitions back its original state when the suspension ends, regardless of the value of transient.

For more information, see Syntax of the audio policy configuration file.”