Depuración de audio

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

  1. cd frameworks/av/services/audioflinger
  2. Edita Configuration.h.
  3. Quita los comentarios de #define TEE_SINK.
  4. Vuelve a compilar libaudioflinger.so.
  5. adb root
  6. adb remount
  7. Envía o sincroniza el libaudioflinger.so nuevo con el /system/lib del dispositivo.

Configuración del entorno de ejecución

  1. adb shell getprop | grep ro.debuggable
    Confirma que el resultado sea [ro.debuggable]: [1]
  2. adb shell
  3. 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
    
  4. echo af.tee=# > /data/local.prop
    El valor af.tee es un número que se describe a continuación.
  5. chmod 644 /data/local.prop
  6. 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

  1. Ejecuta la prueba de audio.
  2. adb shell dumpsys media.audio_flinger
  3. 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.
  4. 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 Resultado dumpsys, pero aún se guardan en /data/misc/audioserver cuando se cierra el segmento.
  5. 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:

  1. Revierte los cambios del código fuente a Configuration.h.
  2. Vuelve a compilar libaudioflinger.so.
  3. Envía o sincroniza el libaudioflinger.so restablecido al /system/lib del dispositivo.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. 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 y FastCapture.
  • 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:

Arquitectura antes de media.log

Figura 1: Arquitectura antes de media.log

Puntos destacados:

  • init bifurca y ejecuta mediaserver.
  • init detecta la muerte de mediaserver 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:

Arquitectura después de media.log

Figura 2: Arquitectura después de media.log

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
El comando 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