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
cd frameworks/av/services/audioflinger
- Modifica
Configuration.h
. - Rimuovi il commento da
#define TEE_SINK
. - Ricrea la build di
libaudioflinger.so
. adb root
adb remount
- Premi o sincronizza il nuovo
libaudioflinger.so
con il dispositivo/system/lib
.
Configurazione in fase di runtime
adb shell getprop | grep ro.debuggable
Verifica che l'output sia:[ro.debuggable]: [1]
adb shell
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
echo af.tee=# > /data/local.prop
Dove il valoreaf.tee
è un numero descritto di seguito.chmod 644 /data/local.prop
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
- Esegui il test audio.
adb shell dumpsys media.audio_flinger
- Cerca una riga nell'output
dumpsys
come questa:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Questo è un file .wav PCM. - 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 Outputdumpsys
, ma vengono comunque salvati in/data/misc/audioserver
alla chiusura della traccia. - 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:
- Ripristina le modifiche al codice sorgente in
Configuration.h
. - Ricrea
libaudioflinger.so
. - Esegui il push o sincronizza il
libaudioflinger.so
ripristinato al/system/lib
del dispositivo. adb shell
rm /data/local.prop
rm /data/misc/audioserver/*.wav
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
eFastCapture
. - 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
:
Aspetti importanti:
init
fork e dirigentemediaserver
.init
rileva la morte dimediaserver
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:
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
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