Este artículo describe algunos consejos y trucos para depurar audio de Android.
fregadero en T
El "tee fregadero" es una función de depuración de AudioFlinger, disponible solo en compilaciones personalizadas, para retener un breve fragmento de audio reciente para su posterior análisis. Esto permite comparar lo que realmente se reprodujo o grabó con lo que se esperaba.
Por motivos de privacidad, el fregadero en T está deshabilitado de forma predeterminada, tanto en tiempo de compilación como en tiempo de ejecución. Para utilizar el fregadero en T, deberá habilitarlo volviendo a compilar y también estableciendo una propiedad. Asegúrese de desactivar esta función una vez que haya terminado de depurar; el fregadero en T no debe dejarse habilitado en las versiones de producción.
Las instrucciones de esta sección son para Android 7.x y versiones posteriores. Para Android 5.x y 6.x, reemplace /data/misc/audioserver
con /data/misc/media
. Además, debe utilizar una compilación de usuario o eng. Si utiliza una compilación de depuración de usuario, desactive la verdad con:
adb root && adb disable-verity && adb reboot
Configuración en tiempo de compilación
-
cd frameworks/av/services/audioflinger
- Editar
Configuration.h
. - Descomentar
#define TEE_SINK
. - Reconstruya
libaudioflinger.so
. -
adb root
-
adb remount
- Empuje o sincronice el nuevo
libaudioflinger.so
con el/system/lib
del dispositivo.
Configuración en tiempo de ejecución
-
adb shell getprop | grep ro.debuggable
Confirme que la salida es:[ro.debuggable]: [1]
-
adb shell
-
ls -ld /data/misc/audioserver
Confirme que la salida es:
drwx------ media media ... media
Si el directorio no existe, créelo de la siguiente manera:
mkdir /data/misc/audioserver
chown media:media /data/misc/audioserver
-
echo af.tee=# > /data/local.prop
Donde el valoraf.tee
es un número que se describe a continuación. -
chmod 644 /data/local.prop
-
reboot
Valores para una 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 característica. Consulte el código en AudioFlinger::AudioFlinger()
en AudioFlinger.cpp
para obtener una explicación de cada bit, pero brevemente:
- 1 = entrada
- 2 = salida FastMixer
- 4 = AudioRecord y AudioTrack por pista
Aún no existe un bit para búfer profundo o mezclador normal, pero puedes obtener resultados similares usando "4".
Probar y adquirir datos
- Ejecute su prueba de audio.
-
adb shell dumpsys media.audio_flinger
- Busque una línea en la salida
dumpsys
como esta:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Este es un archivo PCM .wav. - Luego,
adb pull
cualquier archivo/data/misc/audioserver/*.wav
de interés; tenga en cuenta que los nombres de archivos de volcado específicos de la pista no aparecen en la salidadumpsys
, pero aún así se guardan en/data/misc/audioserver
al cerrar la pista. - Revise los archivos de volcado por cuestiones de privacidad antes de compartirlos con otras personas.
Sugerencias
Pruebe estas ideas para obtener resultados más útiles:
- Desactive los sonidos táctiles y los clics de las teclas para reducir las interrupciones en la salida de la prueba.
- Maximiza todos los volúmenes.
- Desactive las aplicaciones que emiten sonido o graban desde el micrófono, si no son de interés para su prueba.
- Los volcados específicos de la pista sólo se guardan cuando la pista está cerrada; Es posible que tengas que forzar el cierre de una aplicación para poder volcar sus datos específicos de la pista.
- Haga los
dumpsys
inmediatamente después de la prueba; hay una cantidad limitada de espacio de grabación disponible. - Para asegurarse de no perder sus archivos de volcado, cárguelos periódicamente en su host. Sólo se conserva una cantidad limitada de archivos de volcado; Los volcados más antiguos se eliminan una vez que se alcanza ese límite.
Restaurar
Como se señaló anteriormente, la función de fregadero en T no debe dejarse habilitada. Restaure su compilación y dispositivo de la siguiente manera:
- Revierta los cambios del código fuente a
Configuration.h
. - Reconstruya
libaudioflinger.so
. - Empuje o sincronice el
libaudioflinger.so
restaurado con el/system/lib
del dispositivo. -
adb shell
-
rm /data/local.prop
-
rm /data/misc/audioserver/*.wav
-
reboot
medios.log
Macros 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
declarada en <android/log.h>
.
Dentro de la parte nativa del marco de trabajo de Android, preferimos macros denominadas ALOGE
, ALOGW
, ALOGI
, ALOGV
, etc. Se declaran en <utils/Log.h>
y, para los fines de este artículo, nos referiremos a ellas colectivamente como ALOGx
.
Todas estas API son fáciles de usar y bien comprendidas, por lo que están omnipresentes en toda la plataforma Android. En particular, el proceso mediaserver
, que incluye el servidor de sonido AudioFlinger, utiliza ALOGx
ampliamente.
Sin embargo, existen algunas limitaciones para ALOGx
y sus 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 registros no relacionadas, lo que resulta en información perdida. La variante
ALOGV
está deshabilitada en tiempo de compilación de forma predeterminada. Pero, por supuesto, incluso esto puede generar registros de spam si está habilitado. - Las llamadas al sistema del kernel subyacente podrían bloquearse, lo que posiblemente provocaría una inversión de prioridad y, en consecuencia, perturbaciones e imprecisiones en las mediciones. Esto es de especial preocupación para subprocesos en los que el tiempo es crítico, como
FastMixer
yFastCapture
. - Si se deshabilita un registro en particular para reducir el spam de registros, se perderá cualquier información que hubiera sido capturada por ese registro. No es posible habilitar un registro específico de forma retroactiva, después de que quede claro que el registro hubiera sido interesante.
NBLOG, media.log y MediaLogService
Las API NBLOG
y el proceso media.log
asociado y el servicio MediaLogService
juntos forman un sistema de registro más nuevo para medios y están diseñados específicamente para abordar los problemas anteriores. Usaremos libremente el término "media.log" para referirnos a los tres, pero estrictamente hablando, NBLOG
es la API de registro de C++, media.log
es un nombre de proceso de Linux y MediaLogService
es un servicio de carpeta de Android para examinar los registros.
Una "línea de tiempo" media.log
es una serie de entradas de registro cuyo orden relativo se conserva. Por convención, cada hilo debe utilizar su propia línea de tiempo.
Beneficios
Los beneficios del sistema media.log
son que:
- No envía spam al registro principal a menos que sea necesario.
- Se puede examinar incluso cuando
mediaserver
falla o se bloquea. - No bloquea por línea de tiempo.
- Ofrece menos perturbaciones en el rendimiento. (Por supuesto, ninguna forma de registro es completamente no intrusiva).
Arquitectura
El siguiente diagrama muestra la relación entre el proceso mediaserver
y el proceso init
, antes de que se introduzca media.log
:
Puntos notables:
-
init
bifurca y ejecutamediaserver
. -
init
detecta la muerte demediaserver
y vuelve a bifurcarlo según sea necesario. - El registro
ALOGx
no se muestra.
El siguiente diagrama muestra la nueva relación de los componentes, después de agregar media.log
a la arquitectura:
Cambios importantes:
- Los clientes utilizan la API
NBLOG
para crear entradas de registro y agregarlas 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 tal manera que cualquier daño en la memoria compartida no bloqueará
MediaLogService
y aún podrá volcar la mayor parte del búfer que no se vea afectado por la corrupción. - El búfer circular no bloquea ni bloquea tanto para escribir nuevas entradas como para leer entradas existentes.
- No se requieren llamadas al sistema del kernel para escribir o leer desde el búfer circular (aparte de las marcas de tiempo opcionales).
Dónde utilizar
A partir de Android 4.4, solo hay unos pocos puntos de registro en AudioFlinger que utilizan el sistema media.log
. Aunque las nuevas API no son tan fáciles de usar como ALOGx
, tampoco son extremadamente difíciles. Te animamos a conocer el nuevo sistema de registro para aquellas ocasiones en las que sea indispensable. En particular, se recomienda para subprocesos AudioFlinger que deben ejecutarse con frecuencia, periódicamente y sin bloqueos, como los subprocesos FastMixer
y FastCapture
.
Cómo utilizar
Agregar registros
Primero, necesitas agregar registros a tu código.
En los subprocesos FastMixer
y FastCapture
, utilice código como este:
logWriter->log("string"); logWriter->logf("format", parameters); logWriter->logTimestamp();
Como esta línea de tiempo NBLog
solo la utilizan los subprocesos FastMixer
y FastCapture
, no hay necesidad de exclusión mutua.
En otros hilos de AudioFlinger, use mNBLogWriter
:
mNBLogWriter->log("string"); mNBLogWriter->logf("format", parameters); mNBLogWriter->logTimestamp();
Para subprocesos distintos de FastMixer
y FastCapture
, la línea de tiempo NBLog
del subproceso puede ser utilizada tanto por el propio subproceso como por las operaciones de vinculación. NBLog::Writer
no proporciona ninguna exclusión mutua implícita por línea de tiempo, así que asegúrese de que todos los registros ocurran dentro de un contexto donde se mantiene el mutex mLock
del hilo.
Después de haber agregado los registros, reconstruya AudioFlinger.
Precaución: Se requiere una línea de tiempo NBLog::Writer
separada por hilo, para garantizar la seguridad del hilo, ya que las líneas de tiempo omiten mutex por diseño. Si desea que más de un hilo use la misma línea de tiempo, puede protegerlo con un mutex existente (como se describe anteriormente para mLock
). O puede utilizar el contenedor NBLog::LockedWriter
en lugar de NBLog::Writer
. Sin embargo, esto anula un beneficio principal de esta API: su comportamiento sin bloqueo.
La API NBLog
completa se encuentra en frameworks/av/include/media/nbaio/NBLog.h
.
Habilitar media.log
media.log
está deshabilitado de forma predeterminada. Está activo solo cuando la propiedad ro.test_harness
es 1
. Puedes habilitarlo mediante:
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, entonces:
adb shellEl comando
ps media
ahora mostrará dos procesos:- medios.log
- servidor multimedia
Tenga en cuenta el ID del proceso del mediaserver
para más adelante.
Mostrar las líneas de tiempo
Puede solicitar manualmente un volcado de registros en cualquier momento. Este comando muestra registros de todas las líneas de tiempo activas y recientes y luego los borra:
dumpsys media.log
Tenga en cuenta que, por diseño, los cronogramas son independientes y no existe la posibilidad de fusionarlos.
Recuperar registros después de la muerte del servidor de medios
Ahora intente eliminar el proceso mediaserver
: kill -9 #
, donde # es el ID del proceso que anotó anteriormente. Debería ver un volcado de media.log
en el logcat
principal, que muestra todos los registros previos al bloqueo.
dumpsys media.log