La versión de Android 4.1 introdujo cambios en el framework interno para lograr una ruta de salida de audio con menor latencia. Se realizaron cambios mínimos en la API de cliente público o en la API de HAL. En este documento, se describe el diseño inicial, que ha seguido evolucionando con el tiempo. Comprender bien este diseño debería ayudar a los OEM de dispositivos y a los proveedores de SoC a implementar el diseño correctamente en sus dispositivos y conjuntos de chips específicos. Este artículo no está destinado a desarrolladores de aplicaciones.
Creación de segmentos
De manera opcional, el cliente puede establecer el bit AUDIO_OUTPUT_FLAG_FAST
en el parámetro audio_output_flags_t
del constructor de AudioTrack en C++ o en AudioTrack::set()
. Actualmente, los únicos clientes que lo hacen son los siguientes:
- Audio nativo de Android basado en OpenSL ES o AAudio
- android.media.SoundPool
- android.media.ToneGenerator
La implementación de AudioTrack en C++ revisa la solicitud AUDIO_OUTPUT_FLAG_FAST
y, de manera opcional, puede rechazarla a nivel del cliente. Si decide pasar la solicitud, lo hace con el bit TRACK_FAST
del parámetro track_flags_t
del método de fábrica IAudioTrack
IAudioFlinger::createTrack()
.
El servidor de audio AudioFlinger revisa la solicitud TRACK_FAST
y, de manera opcional, puede rechazarla a nivel del servidor. Le informa al cliente si se aceptó o no la solicitud a través del bit CBLK_FAST
del bloque de control de memoria compartida.
Entre los factores que influyen en la decisión, se incluyen los siguientes:
- Presencia de un subproceso de mezclador rápido para este resultado (consulta a continuación)
- Tasa de muestreo de la pista
- Presencia de un subproceso de cliente para ejecutar controladores de devolución de llamada para esta pista
- Tamaño del búfer de la pista
- Los horarios disponibles para el carril rápido (consulta a continuación)
Si se aceptó la solicitud del cliente, se denomina “vía rápida”. De lo contrario, se denomina "pista normal".
Subprocesos de Mixer
En el momento en que AudioFlinger crea un subproceso de mezclador normal, decide si también creará un subproceso de mezclador rápido. Tanto el mezclador normal como el rápido no están asociados con una pista en particular, sino con un conjunto de pistas. Siempre hay un subproceso de mezclador normal. El subproceso de mezclador rápido, si existe, está subordinado al subproceso de mezclador normal y actúa bajo su control.
Batidora rápida
Funciones
El subproceso del mezclador rápido proporciona las siguientes funciones:
- Mezcla de la submezcla del mezclador normal y hasta 7 pistas rápidas del cliente
- Atenuación por pista
Funciones omitidas:
- Conversión de la tasa de muestreo por pista
- Efectos por pista
- Efectos por mezcla
Período
El mezclador rápido se ejecuta de forma periódica, con un período recomendado de dos a tres milisegundos (ms) o un período ligeramente superior de cinco ms si es necesario para programar la estabilidad. Se eligió este número para que, teniendo en cuenta la canalización de búfer completa, la latencia total sea del orden de 10 ms. Es posible usar valores más pequeños, pero es posible que aumente el consumo de energía y la posibilidad de fallas, según la previsibilidad de programación de la CPU. Se pueden usar valores más grandes, de hasta 20 ms, pero se degrada la latencia total, por lo que se deben evitar.
Programación
El mezclador rápido se ejecuta con prioridad SCHED_FIFO
elevada. Necesita muy poco tiempo de CPU, pero debe ejecutarse con frecuencia y con un jitter de programación bajo.
El jitter expresa la variación en el tiempo de ciclo: es la diferencia entre el tiempo de ciclo real y el esperado.
Si se ejecuta demasiado tarde, se producirán fallas debido al subdesbordamiento. Si se ejecuta demasiado pronto, se producirán fallas debido a que se extrae de un segmento rápido antes de que este proporcione datos.
Bloqueo
Idealmente, el subproceso del mezclador rápido nunca se bloquea, excepto en HAL write()
. Otros casos de bloqueo dentro del mezclador rápido se consideran errores. En particular, se evitan los mutex.
En su lugar, se usan algoritmos sin bloqueo (también conocidos como algoritmos sin bloqueo).
Consulta Cómo evitar la inversión de prioridad para obtener más información sobre este tema.
Relación con otros componentes
El mezclador rápido tiene poca interacción directa con los clientes. En particular, no ve las operaciones a nivel del Binder, pero sí accede al bloque de control de memoria compartida del cliente.
El mezclador rápido recibe comandos del mezclador normal a través de una cola de estado.
Además de extraer datos de pistas, la interacción con los clientes se realiza a través del mezclador normal.
El receptor principal del mezclador rápido es el HAL de audio.
Batidora normal
Funciones
Todas las funciones están habilitadas:
- Hasta 32 pistas
- Atenuación por pista
- Conversión de la tasa de muestreo por pista
- Procesamiento de efectos
Período
El período se calcula para ser el primer múltiplo integral del período del mezclador rápido que sea superior o igual a 20 ms.
Programación
El mezclador normal se ejecuta con prioridad SCHED_OTHER
elevada.
Bloqueo
El mezclador normal puede bloquearse y, a menudo, lo hace en varios mutexes, así como en un canal de bloqueo para escribir su submezcla.
Relación con otros componentes
El mezclador normal interactúa de forma extensa con el entorno externo, incluidos los subprocesos de Binder, el administrador de políticas de audio, el subproceso de mezclador rápido y las pistas de cliente.
El sumidero del mezclador normal es un tubo de bloqueo para la pista 0 del mezclador rápido.
Marcas
El bit AUDIO_OUTPUT_FLAG_FAST
es una sugerencia. No hay garantía de que se complete la solicitud.
AUDIO_OUTPUT_FLAG_FAST
es un concepto a nivel del cliente. No aparece en el servidor.
TRACK_FAST
es un concepto de cliente a servidor.