Débogage audio

Cet article présente quelques conseils et astuces pour déboguer les fichiers audio Android.

Évier en T

Le "récupérateur de tee" correspond à une fonctionnalité de débogage AudioFlinger, disponible uniquement dans les builds personnalisés ; permettant de conserver un court fragment de contenu audio récent en vue d'une analyse ultérieure. Cela permet de comparer ce qui a été réellement lu ou enregistré par rapport à ce qui était prévu.

Pour des raisons de confidentialité, le récepteur de te est désactivé par défaut, à la fois au moment de la compilation et lors de l'exécution. Pour utiliser l'évier en T, vous devez l'activer en recompilant, ainsi qu'en définissant une propriété. N'oubliez pas de la désactiver après avoir Terminé le débogage ; le récepteur du T ne doit pas être activé dans les builds de production.

Les instructions de cette section concernent Android 7.x ou version ultérieure. Pour Android 5.x et 6.x, remplacez /data/misc/audioserver par /data/misc/media En outre, vous devez utiliser la méthode userdebug ou eng build. Si vous utilisez une version userdebug, désactivez la vérification avec:

adb root && adb disable-verity && adb reboot

Configuration au moment de la compilation

  1. cd frameworks/av/services/audioflinger
  2. Modifier Configuration.h.
  3. Annulez la mise en commentaire de #define TEE_SINK.
  4. Recompilez libaudioflinger.so.
  5. adb root
  6. adb remount
  7. Déployez ou synchronisez le nouveau libaudioflinger.so sur le /system/lib de l'appareil.

Configuration de l'exécution

  1. adb shell getprop | grep ro.debuggable
    Vérifiez que la sortie est: [ro.debuggable]: [1]
  2. adb shell
  3. ls -ld /data/misc/audioserver

    Vérifiez que la sortie est la suivante:

    drwx------ media media ... media
    

    Si le répertoire n'existe pas, créez-le comme suit:

    mkdir /data/misc/audioserver
    chown media:media /data/misc/audioserver
    
  4. echo af.tee=# > /data/local.prop
    Où la valeur af.tee est un nombre décrit ci-dessous.
  5. chmod 644 /data/local.prop
  6. reboot

Valeurs de la propriété af.tee

La valeur de af.tee est un nombre compris entre 0 et 7, exprimant la somme de plusieurs bits, un par caractéristique. Voir le code sur AudioFlinger::AudioFlinger() dans AudioFlinger.cpp pour une explication de chaque bit, mais brièvement:

  • 1 = entrée
  • 2 = Sortie FastMixer
  • 4 = enregistrement audio et piste audio par piste

Il n'y a pas encore de bit pour le tampon profond ou le mélangeur normal, mais vous pouvez obtenir des résultats similaires en utilisant « 4 ».

Tester et acquérir des données

  1. Exécutez votre test audio.
  2. adb shell dumpsys media.audio_flinger
  3. Recherchez une ligne dans la sortie dumpsys comme celle-ci:
    tee copied to /data/misc/audioserver/20131010101147_2.wav
    Il s'agit d'un fichier PCM .wav.
  4. Ensuite, utilisez adb pull pour tout fichier /data/misc/audioserver/*.wav qui vous intéresse. notez que les noms de fichiers de dump spécifiques aux pistes n'apparaissent pas dans Résultat dumpsys mais elles seront toujours enregistrées dans /data/misc/audioserver lors de la fermeture du canal.
  5. Examinez les fichiers de dump pour vérifier s'ils présentent des problèmes de confidentialité avant de les partager avec d'autres utilisateurs.

Suggestions

Essayez ces idées pour obtenir des résultats plus utiles:

  • Désactivez les sons des touches et les clics sur les touches pour limiter les interruptions du test.
  • Maximisez tous les volumes.
  • Désactivez les applications qui émettent des sons ou enregistrent des images via le micro. s'ils ne présentent pas d'intérêt pour votre test.
  • Les fichiers de dump propres au canal ne sont enregistrés que lorsque le canal est fermé. vous devrez peut-être forcer la fermeture d'une application pour vider les données spécifiques à un canal.
  • Exécutez la commande dumpsys immédiatement après le test. l'espace d'enregistrement disponible est limité.
  • Pour vous assurer de ne pas perdre vos fichiers de dump, et les importer régulièrement sur votre hôte. Seul un nombre limité de fichiers de dump est conservé. les fichiers de vidage plus anciens sont supprimés une fois cette limite atteinte.

Restore

Comme indiqué ci-dessus, il ne faut pas laisser la fonctionnalité de lavabo en te activée. Restaurez votre build et votre appareil comme suit:

  1. Rétablissez les modifications du code source sur Configuration.h.
  2. Recompilez libaudioflinger.so.
  3. Transférez ou synchronisez le libaudioflinger.so restauré au /system/lib de l'appareil.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. reboot

journal.media

Macros ALOGx

L'API de journalisation en langage Java standard dans le SDK Android est la suivante : android.util.Log

L'API en langage C correspondante dans le NDK Android est __android_log_print déclaré dans <android/log.h>.

Dans la partie native du framework Android, préférez les macros ALOGE, ALOGW, ALOGI, ALOGV, etc. Elles sont déclarées dans <utils/Log.h>, et dans le cadre de cet article. nous les appellerons collectivement ALOGx.

Toutes ces API sont faciles à utiliser et bien comprises, et sont donc répandues. sur l'ensemble de la plate-forme Android. en particulier mediaserver. qui inclut le serveur de sons AudioFlinger, utilise ALOGx.

Néanmoins, ALOGx et ses amis présentent certaines limites:

  • Ils sont susceptibles d'être considérés comme du spam dans les journaux : le tampon de journal est une ressource partagée. afin qu'il puisse facilement déborder en raison d'entrées de journal non liées, ce qui entraîne des informations manquées. La variante ALOGV est désactivée à à la compilation par défaut. Bien entendu, cela peut même entraîner des enregistrements de spam dans les journaux s'il est activé.
  • Les appels système du noyau sous-jacent pourraient bloquer, ce qui peut entraîner l'inversion de priorité et, par conséquent, les perturbations de mesure d'inexactitudes. Ceci est de s'inquiète notamment des threads urgents tels que FastMixer et FastCapture.
  • Si un journal spécifique est désactivé pour réduire le spam dans les journaux, alors toutes les informations qui auraient été captivées par ce journal sont perdues. Il n'est pas possible d'activer un journal spécifique rétroactivement, après, il devient clair que le journal aurait été intéressant.

NBLOG, media.log et MediaLogService

Les API NBLOG et les media.log associés processus et MediaLogService forment un système de journalisation des médias plus récent et sont spécifiquement conçu pour résoudre les problèmes ci-dessus. Nous utiliserons vaguement le terme "media.log" pour faire référence à ces trois éléments, mais à proprement parler NBLOG, API de journalisation C++, media.log est un nom de processus Linux et MediaLogService est un service de liaison Android permettant d'examiner les journaux.

Une "chronologie" media.log est une série d'entrées de journal dont l'ordre relatif est conservé. Par convention, chaque thread doit utiliser sa propre chronologie.

Avantages

L'avantage du système media.log est qu'il:

  • N'envoie pas de spam dans le journal principal, sauf si et jusqu'à ce que cela soit nécessaire.
  • Peut être examiné même si mediaserver plante ou se bloque.
  • Elle n'est pas bloquante pour chaque chronologie.
  • Moins de perturbation des performances. Bien sûr, aucune forme de journalisation n'est totalement non intrusive.

Architecture

Le schéma ci-dessous illustre la relation entre le processus mediaserver et le processus init, avant l'introduction de media.log:

Architecture avant media.log

Figure 1 : Architecture avant media.log

Points importants:

  • init duplique et exécute mediaserver.
  • init détecte la mort de mediaserver et effectue une nouvelle duplication si nécessaire.
  • La journalisation ALOGx ne s'affiche pas.

Le schéma ci-dessous montre la nouvelle relation entre les composants, après l'ajout de media.log à l'architecture:

Architecture après media.log

Figure 2. Architecture après media.log

Modifications importantes

  • Les clients utilisent l'API NBLOG pour construire des entrées de journal et les ajouter à un tampon circulaire en mémoire partagée.
  • MediaLogService peut vider le contenu du tampon circulaire à tout moment.
  • Le tampon circulaire est conçu de telle sorte que toute corruption la mémoire partagée ne plantera pas MediaLogService, et l'appareil pourra toujours de vider la plus grande partie du tampon qui n'est pas affectée par la corruption.
  • Le tampon circulaire est non bloquant et sans verrouillage pour l'écriture de nouvelles entrées et en lisant les entrées existantes.
  • Aucun appel système du noyau n'est requis pour lire ou écrire dans le tampon circulaire (à l'exception des codes temporels facultatifs).

Pays dans lesquels Android Auto peut être utilisé

Depuis Android 4.4, les points de journalisation AudioFlinger sont peu nombreux. qui utilisent le système media.log. Bien que les nouvelles API ne soient pas aussi faciles à utiliser en tant que ALOGx, ils ne sont pas non plus très difficiles à utiliser. Nous vous encourageons à vous familiariser avec le nouveau système de journalisation lorsqu'elle est indispensable. Elle est en particulier recommandée pour les threads AudioFlinger qui doivent s'exécutent fréquemment, régulièrement et sans blocage, Threads FastMixer et FastCapture.

Fonctionnement

Ajouter des journaux

Tout d'abord, vous devez ajouter des journaux à votre code.

Dans les threads FastMixer et FastCapture, utilisez un code comme celui-ci:

logWriter->log("string");
logWriter->logf("format", parameters);
logWriter->logTimestamp();

Comme cette chronologie NBLog n'est utilisée que par FastMixer et FastCapture threads, aucune exclusion mutuelle n'est nécessaire.

Dans les autres threads AudioFlinger, utilisez mNBLogWriter:

mNBLogWriter->log("string");
mNBLogWriter->logf("format", parameters);
mNBLogWriter->logTimestamp();

Pour les threads autres que FastMixer et FastCapture, la chronologie NBLog du thread peut être utilisée à la fois par le thread lui-même et par les opérations de liaison. NBLog::Writer ne fournit exclusion mutuelle implicite par timeline : assurez-vous donc que tous les journaux se produisent dans un contexte où le mutex mLock du thread est tenu.

Après avoir ajouté les journaux, recompilez AudioFlinger.

Attention: Une chronologie NBLog::Writer distincte est requise par thread. pour garantir la sécurité des threads, car les timelines omettent les mutex par nature. Si vous souhaitez que plusieurs threads utilisent la même chronologie, vous pouvez protéger mutex existant (comme décrit ci-dessus pour mLock). Vous pouvez également utilisez le wrapper NBLog::LockedWriter au lieu de NBLog::Writer. Cependant, cela annule l'un des principaux avantages de cette API: sa capacité non bloquante comportemental.

La version complète de l'API NBLog est disponible à l'adresse frameworks/av/include/media/nbaio/NBLog.h.

Activer media.log

media.log est désactivé par défaut. Il n'est actif que si la propriété ro.test_harness est 1. Vous pouvez l'activer en procédant comme suit:

adb root
adb shell
echo ro.test_harness=1 > /data/local.prop
chmod 644 /data/local.prop
reboot

La connexion est perdue au redémarrage. Par conséquent:

adb shell
La commande ps media affiche maintenant deux processus: <ph type="x-smartling-placeholder">
    </ph>
  • journal.media
  • serveurde médias

Notez l'ID de processus mediaserver pour plus tard.

Afficher les chronologies

Vous pouvez demander manuellement un vidage de journal à tout moment. Cette commande affiche les journaux de toutes les chronologies actives et récentes, puis les efface:

dumpsys media.log

Les chronologies sont, par nature, indépendantes et il n'est pas possible de fusionner les chronologies.

Récupérer les journaux après l'arrêt du serveur multimédia

Essayez maintenant de fermer le processus mediaserver: kill -9 #, où # est l'ID de processus que vous avez noté précédemment. Un fichier de vidage de media.log devrait s'afficher. dans le logcat principal, affichant tous les journaux ayant précédé le plantage.

dumpsys media.log