En este artículo, se describen algunas sugerencias y trucos para depurar audio de Android.
Fregadero en forma de te
El "fregadero de té" es una función de depuración de AudioFlinger, disponible solo en compilaciones personalizadas para retener un breve fragmento de audio reciente para su análisis posterior. Esto permite comparar lo que se reprodujo o grabó en realidad. en comparación con lo que se esperaba.
Por cuestiones de privacidad, el receptor de tee está inhabilitado de forma predeterminada, tanto en el tiempo de compilación como durante el tiempo de ejecución. Para usar el receptor de tee, tendrás que habilitarlo volviendo a compilar, y también estableciendo una propiedad. Asegúrate de inhabilitar esta función después de que realizar la depuración; el receptor de tee no debe dejarse habilitado en las compilaciones de producción.
Las instrucciones de esta sección son para Android 7.x y versiones posteriores. Para Android
5.x y 6.x, reemplazar /data/misc/audioserver
por
/data/misc/media
Además, debes usar userdebug o
eng. Si usas una compilación userdebug, inhabilita verity con:
adb root && adb disable-verity && adb reboot
Configuración del tiempo de compilación
cd frameworks/av/services/audioflinger
- Edita
Configuration.h
. - Quita los comentarios de
#define TEE_SINK
. - Vuelve a compilar
libaudioflinger.so
. adb root
adb remount
- Envía o sincroniza el
libaudioflinger.so
nuevo con el/system/lib
del dispositivo.
Configuración del entorno de ejecución
adb shell getprop | grep ro.debuggable
Confirma que el resultado sea[ro.debuggable]: [1]
adb shell
ls -ld /data/misc/audioserver
Confirma que el resultado sea el siguiente:
drwx------ media media ... media
Si el directorio no existe, créalo de la siguiente manera:
mkdir /data/misc/audioserver
chown media:media /data/misc/audioserver
echo af.tee=# > /data/local.prop
El valoraf.tee
es un número que se describe a continuación.chmod 644 /data/local.prop
reboot
Valores de la propiedad af.tee
El valor de af.tee
es un número entre 0 y 7, que expresa
la suma de varios bits, uno por atributo.
Consulta el código en AudioFlinger::AudioFlinger()
(AudioFlinger.cpp
)
para obtener una explicación de cada parte, pero de forma breve:
- 1 = entrada
- 2 = Salida del FastMixer
- 4 = AudioRecord y AudioTrack por pista
Todavía no hay bits para el búfer profundo o el mezclador normal. pero puedes obtener resultados similares si usas "4".
Prueba y adquiere datos
- Ejecuta la prueba de audio.
adb shell dumpsys media.audio_flinger
- Busca una línea en el resultado de
dumpsys
como la siguiente:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Este es un archivo PCM .wav. - Luego, usa
adb pull
para los archivos/data/misc/audioserver/*.wav
de interés. Ten en cuenta que los nombres de archivo de volcado específicos de la pista no aparecen en el Resultadodumpsys
, pero aún se guardan en/data/misc/audioserver
cuando se cierra el segmento. - Revisa los archivos de volcado para detectar inquietudes sobre la privacidad antes de compartirlos con otras personas.
Sugerencias
Prueba estas ideas para obtener resultados más útiles:
- Inhabilita los sonidos táctiles y los clics de teclas para reducir las interrupciones en la salida de la prueba.
- Maximizar todos los volúmenes.
- Inhabilitar aplicaciones que emiten sonido o graban desde el micrófono si no son de interés para tu prueba.
- Los volcados específicos de segmentos solo se guardan cuando estos se cierran. Es posible que debas forzar el cierre de una app para volcar los datos específicos de los segmentos
- Realiza el
dumpsys
inmediatamente después de la prueba. el espacio de grabación es limitado. - Para asegurarte de no perder los archivos de volcado, haz lo siguiente: súbelas al host de forma periódica. Solo se conserva una cantidad limitada de archivos de volcado. Se quitan los volcados más antiguos una vez que se alcanza ese límite.
Restablecer
Como se indicó anteriormente, la función del receptor de tee no se debe dejar habilitada. Restablece la compilación y el dispositivo de la siguiente manera:
- Revierte los cambios del código fuente a
Configuration.h
. - Vuelve a compilar
libaudioflinger.so
. - Envía o sincroniza el
libaudioflinger.so
restablecido al/system/lib
del dispositivo. adb shell
rm /data/local.prop
rm /data/misc/audioserver/*.wav
reboot
media.log
Macros de ALOGx
La API de registro del lenguaje Java estándar en el SDK de Android es android.util.Log
La API de lenguaje C correspondiente en el NDK de Android es
__android_log_print
declarado en <android/log.h>
.
En la parte nativa del framework de Android,
prefieren las macros llamadas ALOGE
, ALOGW
,
ALOGI
, ALOGV
, etc. Se declaran en
<utils/Log.h>
. A los efectos de este artículo,
nos referiremos a ellos en conjunto como ALOGx
.
Todas estas APIs son fáciles de usar y de fácil comprensión, por lo que están generalizadas
en toda la plataforma de Android. En particular, el elemento mediaserver
que incluye el servidor de sonido AudioFlinger, usa
ALOGx
por completo.
Sin embargo, existen algunas limitaciones para ALOGx
y amigos:
-
Son susceptibles al “spam de registros”: el búfer de registros es un recurso compartido.
por lo que puede desbordarse fácilmente debido a entradas de registro no relacionadas, lo que genera una
información perdida. La variante
ALOGV
está inhabilitada en tiempo de compilación de forma predeterminada. Pero, por supuesto, incluso puede generar spam de registros si está habilitada. -
Se podrían bloquear las llamadas al sistema de kernel subyacente, lo que podría generar
la inversión de prioridad y, por consiguiente, las alteraciones en la medición y
imprecisiones. Esto es de
especial atención a los subprocesos críticos para el tiempo, como
FastMixer
yFastCapture
. - Si se inhabilita un registro específico para reducir el spam, se pierde cualquier información que hubiera capturado ese registro. No es posible habilitar un registro específico de forma retroactiva después, queda claro que el registro hubiera sido interesante.
NBLOG, media.log y MediaLogService
Las APIs de NBLOG
y los media.log
asociados
proceso y MediaLogService
juntos forman un sistema de registro más nuevo para los medios, y se usan
diseñados para abordar los problemas antes mencionados. Usaremos vagamente el término
“media.log” para referirnos a los tres, pero, en rigor, NBLOG
es la
API de Logging de C++, media.log
es un nombre de proceso de Linux y MediaLogService
.
es un servicio de carpetas de Android para examinar los registros.
Un "cronograma" media.log
es una serie
de entradas de registro cuyo orden relativo se preserva.
Por convención, cada subproceso debe usar su propio cronograma.
Beneficios
Los beneficios del sistema media.log
son los siguientes:
- No genera spam en el registro principal, a menos que sea necesario.
- Se puede examinar incluso cuando
mediaserver
falla o se bloquea. - No genera bloqueos por cronograma.
- Ofrece menos interrupciones en el rendimiento. (Por supuesto, ninguna forma de registro es completamente no intrusiva).
Arquitectura
En el siguiente diagrama, se muestra la relación del proceso mediaserver
y el proceso init
, antes de la introducción de media.log
:
Puntos destacados:
init
bifurca y ejecutamediaserver
.init
detecta la muerte demediaserver
y vuelve a bifurcarla según sea necesario.- No se muestra el registro de
ALOGx
.
En el siguiente diagrama, se muestra la relación nueva de los componentes:
después de agregar media.log
a la arquitectura:
Cambios importantes:
-
Los clientes usan la API de
NBLOG
para construir entradas de registro y adjuntarlas a un búfer circular en la memoria compartida. -
MediaLogService
puede volcar el contenido del búfer circular en cualquier momento. -
El búfer circular está diseñado de manera que cualquier corrupción de la
la memoria compartida no fallará
MediaLogService
, y aún podrá volcar la mayor parte del búfer que no se ve afectada por la corrupción. - El búfer circular no genera bloqueos ni bloqueos para la escritura. para crear entradas nuevas y leer las existentes.
- No se requieren llamadas al sistema kernel para escribir o leer desde el búfer circular. (excepto las marcas de tiempo opcionales).
Dónde puedes usarlo
A partir de Android 4.4, solo hay unos pocos puntos de registro en AudioFlinger.
que usan el sistema media.log
. Aunque las nuevas APIs no son tan
fáciles de usar como ALOGx
, tampoco son muy difíciles de usar.
Te recomendamos que aprendas sobre el nuevo sistema de registro para quienes
ocasiones en las que es indispensable.
En particular, se recomienda para subprocesos de AudioFlinger que deben
se ejecutan con frecuencia, de forma periódica y sin bloqueos, como
Subprocesos FastMixer
y FastCapture
.
How to use
Agregar registros
Primero, debes agregar registros a tu código.
En los subprocesos FastMixer
y FastCapture
, usa código como el siguiente:
logWriter->log("string"); logWriter->logf("format", parameters); logWriter->logTimestamp();
Como esta NBLog
línea de tiempo solo la usan FastMixer
y
FastCapture
conversaciones,
no hay necesidad de exclusión mutua.
En otros subprocesos de AudioFlinger, usa mNBLogWriter
:
mNBLogWriter->log("string"); mNBLogWriter->logf("format", parameters); mNBLogWriter->logTimestamp();
En el caso de los subprocesos que no sean FastMixer
ni FastCapture
,
El cronograma NBLog
del subproceso puede ser utilizado tanto por el subproceso en sí como
por operaciones de Binder. NBLog::Writer
no proporciona
exclusión mutua implícita por cronograma, así que asegúrate de que todos los registros ocurran
en un contexto en el que se conserva la exclusión mutua de mLock
del subproceso.
Después de agregar los registros, vuelve a compilar AudioFlinger.
Precaución:
Se requiere un cronograma de NBLog::Writer
independiente por subproceso.
para garantizar la seguridad de los subprocesos, ya que los cronogramas omiten las exclusiones mutuas por diseño. Si
deseas que más de un subproceso usen la misma línea de tiempo, puedes protegerlos con un
exclusión mutua existente (como se describió anteriormente para mLock
). O puedes
Usa el wrapper NBLog::LockedWriter
en lugar de NBLog::Writer
.
Sin embargo, esto anula un beneficio primordial de esta API: su
el comportamiento de los usuarios.
La API completa de NBLog
se encuentra en frameworks/av/include/media/nbaio/NBLog.h
.
Habilita media.log
media.log
está inhabilitado de forma predeterminada. Solo se activa cuando la propiedad
ro.test_harness
es 1
. Para habilitarlo, haz lo siguiente:
adb root
adb shell
echo ro.test_harness=1 > /data/local.prop
chmod 644 /data/local.prop
reboot
La conexión se pierde durante el reinicio, por lo que sucede lo siguiente:
adb shell
ps media
ahora mostrará dos procesos:
- .
- media.log
- mediaserver
Toma nota del ID de proceso de mediaserver
para usar más adelante.
Cómo mostrar los cronogramas
Puedes solicitar un volcado de registros de forma manual en cualquier momento. Este comando muestra los registros de todos los cronogramas activos y recientes y, luego, los borra:
dumpsys media.log
Ten en cuenta que, por su diseño, los cronogramas son independientes y no hay recurso para combinar líneas de tiempo.
Recupera registros después del cierre de mediaserver
Ahora intenta finalizar el proceso mediaserver
: kill -9 #
, donde # es
el ID de proceso que anotaste antes. Deberías ver un volcado de media.log
En el logcat
principal, que muestra todos los registros que llevaron a la falla.
dumpsys media.log