Debug audio

In questo articolo vengono descritti alcuni suggerimenti utili per il debug dell'audio dei dispositivi Android.

Lavabo a T

"Tee sink" sono è una funzionalità di debug AudioFlinger, disponibile solo in build personalizzate, per conservare un breve frammento di audio recente per analisi successive. In questo modo è possibile confrontare i contenuti effettivamente riprodotti o registrati rispetto alle aspettative.

Per motivi di privacy, il sink tee è disabilitato per impostazione predefinita, sia in fase di compilazione che in fase di esecuzione. Per usare il sink a T, dovrai abilitarlo ricompilando, sia impostando una proprietà. Assicurati di disattivare questa funzione dopo aver completato il debug; il sink a tee non deve essere lasciato abilitato nelle build di produzione.

Le istruzioni in questa sezione si riferiscono ad Android 7.x e versioni successive. Per Android 5.x e 6.x, sostituisci /data/misc/audioserver con /data/misc/media. Inoltre, devi utilizzare un comando eng build. Se utilizzi una build di debug dell'utente, disabilita la verifica con:

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

Configurazione del tempo di compilazione

  1. cd frameworks/av/services/audioflinger
  2. Modifica Configuration.h.
  3. Rimuovi il commento da #define TEE_SINK.
  4. Ricrea libaudioflinger.so.
  5. adb root
  6. adb remount
  7. Premi o sincronizza il nuovo libaudioflinger.so con il dispositivo /system/lib.

Configurazione in fase di runtime

  1. adb shell getprop | grep ro.debuggable
    Verifica che l'output sia: [ro.debuggable]: [1]
  2. adb shell
  3. ls -ld /data/misc/audioserver

    Verifica che l'output sia:

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

    Se la directory non esiste, creala come segue:

    mkdir /data/misc/audioserver
    chown media:media /data/misc/audioserver
    
  4. echo af.tee=# > /data/local.prop
    Dove il valore af.tee è un numero descritto di seguito.
  5. chmod 644 /data/local.prop
  6. reboot

Valori per la proprietà af.tee

Il valore di af.tee è un numero compreso tra 0 e 7, che esprime la somma di diversi bit, uno per caratteristica. Visualizza il codice alla pagina AudioFlinger::AudioFlinger() in AudioFlinger.cpp per una spiegazione di ogni parte, ma brevemente:

  • 1 = input
  • 2 = uscita FastMixer
  • 4 = AudioRecord e AudioTrack per traccia

Non c'è ancora un po' di deep buffer o mixer normale, ma puoi ottenere risultati simili utilizzando "4."

Testare e acquisire dati

  1. Esegui il test audio.
  2. adb shell dumpsys media.audio_flinger
  3. Cerca una riga nell'output dumpsys come questa:
    tee copied to /data/misc/audioserver/20131010101147_2.wav
    Questo è un file .wav PCM.
  4. Poi adb pull tutti i /data/misc/audioserver/*.wav file che ti interessano; i nomi dei file di dump specifici della traccia non vengono visualizzati Output dumpsys, ma vengono comunque salvati in /data/misc/audioserver alla chiusura della traccia.
  5. Esamina i file dump per verificare che non ci siano problemi di privacy prima di condividerli con altri.

Suggerimenti

Per ottenere risultati più utili, prova queste idee:

  • Disattiva i suoni alla pressione e i clic sui tasti per ridurre le interruzioni nell'output di prova.
  • Massimizza tutti i volumi.
  • Disattiva le app che emettono suoni o registrano dal microfono. se non sono interessanti per il tuo test.
  • I dump specifici del canale vengono salvati solo quando il canale è chiuso. potresti dover forzare la chiusura di un'app per eseguire il dump dei dati specifici del canale
  • Esegui dumpsys subito dopo il test. lo spazio di registrazione disponibile è limitato.
  • Per assicurarti di non perdere i file di dump, e caricarle periodicamente sul tuo host. Viene conservato solo un numero limitato di file di dump. i dump meno recenti vengono rimossi al raggiungimento di questo limite.

Ripristina

Come indicato in precedenza, la funzionalità del sink dati non deve essere lasciata abilitata. Ripristina la build e il dispositivo come segue:

  1. Ripristina le modifiche al codice sorgente in Configuration.h.
  2. Ricrea libaudioflinger.so.
  3. Esegui il push o sincronizza il libaudioflinger.so ripristinato al /system/lib del dispositivo.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. reboot

media.log

Macro ALOGx

L'API di logging del linguaggio Java standard nell'SDK per Android è android.util.Log.

L'API del linguaggio C corrispondente in Android NDK è __android_log_print dichiarato in <android/log.h>.

Nella parte nativa del framework Android, preferisci le macro denominate ALOGE, ALOGW, ALOGI, ALOGV e così via. Sono dichiarati in <utils/Log.h> e ai fini di questo articolo collettivamente, ci riferiremo a questi elementi come ALOGx.

Tutte queste API sono facili da usare e ben comprese, per cui sono sempre più pervasive disponibili su tutta la piattaforma Android. In particolare, mediaserver che include il server audio AudioFlinger, utilizza ALOGx in modo esteso.

Tuttavia, esistono alcune limitazioni per ALOGx e i suoi amici:

  • Sono suscettibili di "spam nei log": il buffer di log è una risorsa condivisa in modo che possa facilmente overflow a causa di voci di log non correlate, o se non sono presenti informazioni. La variante ALOGV è disattivata in per impostazione predefinita. Ovviamente anche questo può causare log spam se abilitato.
  • Le chiamate di sistema del kernel sottostanti potrebbero bloccarsi, causando dell'inversione della priorità e, di conseguenza, i disturbi della misurazione e inesattezze. Questo è di particolare attenzione ai thread urgenti, come FastMixer e FastCapture.
  • Se un determinato log viene disabilitato per ridurre lo spam, tutte le informazioni acquisite dal log andranno perse. Non è possibile abilitare un log specifico in modo retroattivo, dopo che diventa chiaro che il log sarebbe stato interessante.

NBLOG, media.log e MediaLogService

Le API NBLOG e media.log associati processo e MediaLogService insieme formano un sistema di logging più recente per i contenuti multimediali e sono in particolare progettata per risolvere i problemi soprattutto. Useremo il termine "media.log" per fare riferimento a tutti e tre, ma NBLOG è la API di logging C++, media.log è un nome di processo Linux e MediaLogService è un servizio di legatura Android per l'esame dei log.

Una "sequenza temporale" media.log è una serie di voci di log il cui ordine relativo viene mantenuto. Per convenzione, ogni thread deve utilizzare la propria sequenza temporale.

Vantaggi

I vantaggi del sistema media.log sono che:

  • Non invia spam al log principale, a meno che e finché non sia necessario.
  • Può essere esaminato anche se mediaserver si arresta in modo anomalo o si blocca.
  • Non blocca in base alla sequenza temporale.
  • Interferisce meno alle prestazioni. (Ovviamente nessuna forma di logging è completamente non invasiva.)

Architettura

Il diagramma seguente mostra la relazione del processo mediaserver e il processo init, prima dell'introduzione di media.log:

Architettura prima di media.log

Figura 1. Architettura prima di media.log

Aspetti importanti:

  • init fork e dirigente mediaserver.
  • init rileva la morte di mediaserver e, se necessario, esegue nuovamente fork.
  • Il logging di ALOGx non viene visualizzato.

Il diagramma seguente mostra la nuova relazione dei componenti, dopo l'aggiunta di media.log all'architettura:

Architettura dopo media.log

Figura 2. Architettura dopo media.log

Modifiche importanti:

  • I client utilizzano l'API NBLOG per creare le voci di log e aggiungerle alla un buffer circolare nella memoria condivisa.
  • MediaLogService può eseguire il dump dei contenuti del buffer circolare in qualsiasi momento.
  • Il buffer circolare è progettato in modo tale che qualsiasi danneggiamento del la memoria condivisa non causerà l'arresto anomalo di MediaLogService e potrà comunque per eseguire il dump della porzione di buffer non interessata dal danneggiamento.
  • Il buffer circolare non blocca né blocchi per la scrittura nuove voci e la lettura di quelle esistenti.
  • Non sono necessarie chiamate di sistema kernel per scrivere o leggere dal buffer circolare (diversi dai timestamp facoltativi).

Paesi in cui è disponibile Android Auto

A partire da Android 4.4, sono presenti solo pochi punti di log in AudioFlinger. che utilizzano il sistema media.log. Anche se le nuove API non sono facili da usare come ALOGx, nemmeno questi sono estremamente difficili. Ti invitiamo a conoscere il nuovo sistema di logging per coloro nelle occasioni in cui è indispensabile. In particolare, è consigliato per i thread AudioFlinger che devono vengono eseguiti di frequente, periodicamente e senza blocchi come FastMixer e FastCapture thread.

Modalità di utilizzo

Aggiungi log

Innanzitutto, devi aggiungere i log al codice.

Nei thread FastMixer e FastCapture, utilizza un codice come questo:

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

Poiché questa sequenza temporale di NBLog viene utilizzata solo da FastMixer e FastCapture thread, non c'è bisogno di esclusione reciproca.

In altri thread AudioFlinger, usa mNBLogWriter:

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

Per i thread diversi da FastMixer e FastCapture: la sequenza temporale NBLog del thread può essere utilizzata sia dal thread stesso sia da operazioni di binder. NBLog::Writer non fornisce esclusione reciproca implicita per sequenza temporale, quindi assicurati che si verifichino tutti i log in un contesto in cui si trova il mutex mLock del thread.

Dopo aver aggiunto i log, ricrea AudioFlinger.

Attenzione: È richiesta una sequenza temporale NBLog::Writer separata per thread, per garantire la sicurezza dei thread, dato che le sequenze temporali omettono i mutex per definizione. Se vuoi che più thread usino la stessa sequenza temporale, puoi proteggere con mutex esistente (come descritto sopra per mLock). Oppure puoi usa il wrapper NBLog::LockedWriter anziché NBLog::Writer. Tuttavia, ciò annulla un importante vantaggio di questa API: la sua capacità comportamento degli utenti.

L'API NBLog completa è disponibile all'indirizzo frameworks/av/include/media/nbaio/NBLog.h.

Attiva media.log

media.log è disattivato per impostazione predefinita. È attivo solo quando la proprietà ro.test_harness è 1. Puoi abilitarlo:

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

La connessione si interrompe durante il riavvio, quindi:

adb shell
Il comando ps media ora mostrerà due processi:
    .
  • media.log
  • mediaserver

Prendi nota dell'ID di processo mediaserver per un secondo momento.

Visualizzare le cronologie

Puoi richiedere manualmente un dump dei log in qualsiasi momento. Questo comando mostra i log di tutte le sequenze temporali attive e recenti e li cancella:

dumpsys media.log

Tieni presente che, per definizione, le tempistiche sono indipendenti, e non c'è nessuna struttura per unire le tempistiche.

Recupera i log dopo la morte del server media

Ora prova ad terminare il processo mediaserver: kill -9 #, dove # è l'ID di processo che hai annotato in precedenza. Dovresti vedere un dump di media.log nella logcat principale, che mostra tutti i log che hanno portato all'arresto anomalo.

dumpsys media.log