Artikel ini menjelaskan beberapa tip dan trik untuk men-debug audio Android.
Wastafel
"Tee sink" adalah fitur debug AudioFlinger, hanya tersedia dalam versi kustom, untuk menyimpan fragmen pendek audio terbaru untuk analisis nanti. Ini memungkinkan perbandingan antara apa yang sebenarnya dimainkan atau direkam vs. apa yang diharapkan.
Untuk privasi, wastafel tee dinonaktifkan secara default, pada waktu kompilasi dan waktu berjalan. Untuk menggunakan wastafel tee, Anda harus mengaktifkannya dengan mengkompilasi ulang, dan juga dengan menyetel properti. Pastikan untuk menonaktifkan fitur ini setelah Anda selesai men-debug; wastafel tee tidak boleh dibiarkan diaktifkan di build produksi.
Petunjuk di bagian ini adalah untuk Android 7.x dan lebih tinggi. Untuk Android 5.x dan 6.x, ganti /data/misc/audioserver dengan /data/misc/media . Selain itu, Anda harus menggunakan userdebug atau eng build. Jika Anda menggunakan build userdebug, nonaktifkan verity dengan:
adb root && adb disable-verity && adb reboot
Pengaturan waktu kompilasi
-
cd frameworks/av/services/audioflinger - Edit
Configuration.h. - Batalkan komentar
#define TEE_SINK. - Bangun
libaudioflinger.so. -
adb root -
adb remount - Dorong atau sinkronkan
libaudioflinger.sobaru ke/system/libperangkat.
Pengaturan waktu berjalan
-
adb shell getprop | grep ro.debuggable
Konfirmasikan bahwa outputnya adalah:[ro.debuggable]: [1] -
adb shell -
ls -ld /data/misc/audioserverKonfirmasikan bahwa outputnya adalah:
drwx------ media media ... media
Jika direktori tidak ada, buat sebagai berikut:
mkdir /data/misc/audioserverchown media:media /data/misc/audioserver -
echo af.tee=# > /data/local.prop
Di mana nilaiaf.teeadalah angka yang dijelaskan di bawah ini. -
chmod 644 /data/local.prop -
reboot
Nilai untuk properti af.tee
Nilai af.tee adalah angka antara 0 dan 7, yang menyatakan jumlah dari beberapa bit, satu bit per fitur. Lihat kode di AudioFlinger::AudioFlinger() di AudioFlinger.cpp untuk penjelasan setiap bit, tetapi secara singkat:
- 1 = masukan
- 2 = keluaran FastMixer
- 4 = AudioRecord dan AudioTrack per trek
Tidak ada sedikit pun untuk buffer dalam atau mixer normal, tetapi Anda bisa mendapatkan hasil yang serupa menggunakan "4."
Menguji dan memperoleh data
- Jalankan tes audio Anda.
-
adb shell dumpsys media.audio_flinger - Cari baris di output
dumpsysseperti ini:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Ini adalah file .wav PCM. - Kemudian
adb pullfile/data/misc/audioserver/*.wavyang diinginkan; perhatikan bahwa nama file dump khusus trek tidak muncul di outputdumpsys, tetapi masih disimpan ke/data/misc/audioserversetelah trek ditutup. - Tinjau file dump untuk masalah privasi sebelum berbagi dengan orang lain.
Saran
Cobalah ide-ide ini untuk hasil yang lebih bermanfaat:
- Nonaktifkan suara sentuh dan klik tombol untuk mengurangi interupsi dalam hasil pengujian.
- Maksimalkan semua volume.
- Nonaktifkan aplikasi yang mengeluarkan suara atau merekam dari mikrofon, jika tidak menarik untuk pengujian Anda.
- Tempat pembuangan khusus trek hanya disimpan saat trek ditutup; Anda mungkin perlu menutup paksa aplikasi untuk membuang data khusus treknya
- Lakukan
dumpsyssegera setelah tes; ada jumlah terbatas ruang perekaman yang tersedia. - Untuk memastikan Anda tidak kehilangan file dump, unggah ke host Anda secara berkala. Hanya sejumlah file dump yang disimpan; dump lama dihapus setelah batas itu tercapai.
Memulihkan
Seperti disebutkan di atas, fitur wastafel tee tidak boleh dibiarkan diaktifkan. Pulihkan build dan perangkat Anda sebagai berikut:
- Kembalikan perubahan kode sumber ke
Configuration.h. - Bangun
libaudioflinger.so. - Dorong atau sinkronkan
libaudioflinger.soyang dipulihkan ke/system/libperangkat. -
adb shell -
rm /data/local.prop -
rm /data/misc/audioserver/*.wav -
reboot
media.log
makro ALOGx
API logging bahasa Java standar di Android SDK adalah android.util.Log .
API bahasa C yang sesuai di Android NDK adalah __android_log_print yang dideklarasikan di <android/log.h> .
Dalam bagian asli kerangka kerja Android, kami lebih memilih makro bernama ALOGE , ALOGW , ALOGI , ALOGV , dll. Mereka dideklarasikan di <utils/Log.h> , dan untuk tujuan artikel ini kami akan secara kolektif menyebutnya sebagai ALOGx .
Semua API ini mudah digunakan dan dipahami dengan baik, sehingga tersebar di seluruh platform Android. Khususnya proses server media, yang mencakup server suara mediaserver , menggunakan ALOGx secara ekstensif.
Namun demikian, ada beberapa batasan untuk ALOGx dan teman-teman:
- Mereka rentan terhadap "log spam": buffer log adalah sumber daya bersama sehingga dapat dengan mudah meluap karena entri log yang tidak terkait, mengakibatkan informasi yang terlewat. Varian
ALOGVdinonaktifkan pada waktu kompilasi secara default. Tapi tentu saja itu bisa mengakibatkan log spam jika diaktifkan. - Panggilan sistem kernel yang mendasari dapat memblokir, mungkin mengakibatkan inversi prioritas dan akibatnya gangguan pengukuran dan ketidakakuratan. Ini menjadi perhatian khusus untuk utas kritis waktu seperti
FastMixerdanFastCapture. - Jika log tertentu dinonaktifkan untuk mengurangi spam log, maka informasi apa pun yang akan ditangkap oleh log tersebut akan hilang. Tidak mungkin untuk mengaktifkan log tertentu secara surut, setelah menjadi jelas bahwa log tersebut akan menarik.
NBLOG, media.log, dan Layanan MediaLog
API NBLOG dan proses media.log terkait serta layanan MediaLogService bersama-sama membentuk sistem pencatatan yang lebih baru untuk media, dan dirancang khusus untuk mengatasi masalah di atas. Kami akan secara longgar menggunakan istilah "media.log" untuk merujuk ke ketiganya, tetapi NBLOG adalah API logging C++, media.log adalah nama proses Linux, dan MediaLogService adalah layanan pengikat Android untuk memeriksa log.
"Garis waktu" media.log adalah serangkaian entri log yang urutan relatifnya dipertahankan. Dengan konvensi, setiap utas harus menggunakan garis waktunya sendiri.
Manfaat
Manfaat sistem media.log adalah:
- Tidak melakukan spam pada log utama kecuali dan sampai diperlukan.
- Dapat diperiksa bahkan ketika
mediaservercrash atau hang. - Non-blocking per timeline.
- Menawarkan lebih sedikit gangguan pada kinerja. (Tentu saja tidak ada bentuk logging yang benar-benar tidak mengganggu.)
Arsitektur
Diagram di bawah menunjukkan hubungan proses mediaserver dan proses init , sebelum media.log diperkenalkan:

Gambar 1. Arsitektur sebelum media.log
Poin penting:
-
initfork dan execsmediaserver. -
initmendeteksi kematianmediaserver, dan melakukan fork ulang seperlunya. - Pencatatan log
ALOGxtidak ditampilkan.
Diagram di bawah ini menunjukkan hubungan baru dari komponen, setelah media.log ditambahkan ke arsitektur:

Gambar 2. Arsitektur setelah media.log
Perubahan penting:
- Klien menggunakan
NBLOGAPI untuk membuat entri log dan menambahkannya ke buffer melingkar di memori bersama. -
MediaLogServicedapat membuang konten buffer melingkar kapan saja. - Buffer melingkar dirancang sedemikian rupa sehingga setiap kerusakan pada memori bersama tidak akan merusak
MediaLogService, dan masih dapat membuang sebanyak mungkin buffer yang tidak terpengaruh oleh kerusakan tersebut. - Buffer melingkar tidak memblokir dan bebas kunci untuk menulis entri baru dan membaca entri yang ada.
- Tidak ada panggilan sistem kernel yang diperlukan untuk menulis atau membaca dari buffer melingkar (selain cap waktu opsional).
Di mana menggunakan
Pada Android 4.4, hanya ada beberapa titik log di AudioFlinger yang menggunakan sistem media.log . Meskipun API baru tidak semudah digunakan seperti ALOGx , mereka juga tidak terlalu sulit. Kami mendorong Anda untuk mempelajari sistem logging baru untuk saat-saat yang sangat diperlukan. Secara khusus, disarankan untuk utas AudioFlinger yang harus sering dijalankan, secara berkala, dan tanpa pemblokiran seperti FastMixer dan FastCapture .
Cara Penggunaan
Tambahkan log
Pertama, Anda perlu menambahkan log ke kode Anda.
Di FastMixer dan FastCapture , gunakan kode seperti ini:
logWriter->log("string");
logWriter->logf("format", parameters);
logWriter->logTimestamp();
Karena garis waktu NBLog ini hanya digunakan oleh FastMixer dan FastCapture , tidak perlu ada pengecualian bersama.
Di utas AudioFlinger lainnya, gunakan mNBLogWriter :
mNBLogWriter->log("string");
mNBLogWriter->logf("format", parameters);
mNBLogWriter->logTimestamp();
Untuk utas selain FastMixer dan FastCapture , garis waktu NBLog dapat digunakan oleh utas itu sendiri, dan oleh operasi pengikat. NBLog::Writer tidak memberikan pengecualian timbal balik implisit per garis waktu, jadi pastikan bahwa semua log terjadi dalam konteks di mana mutex mLock disimpan.
Setelah Anda menambahkan log, buat ulang AudioFlinger.
Perhatian: Garis waktu NBLog::Writer terpisah diperlukan per utas, untuk memastikan keamanan utas, karena garis waktu menghilangkan mutex berdasarkan desain. Jika Anda ingin lebih dari satu utas menggunakan garis waktu yang sama, Anda dapat melindungi dengan mutex yang ada (seperti yang dijelaskan di atas untuk mLock ). Atau Anda dapat menggunakan pembungkus NBLog::LockedWriter alih-alih NBLog::Writer . Namun, ini meniadakan manfaat utama dari API ini: perilakunya yang tidak memblokir.
API NBLog lengkap ada di frameworks/av/include/media/nbaio/NBLog.h .
Aktifkan media.log
media.log dinonaktifkan secara default. Ini aktif hanya jika properti ro.test_harness adalah 1 . Anda dapat mengaktifkannya dengan:
adb rootadb shellecho ro.test_harness=1 > /data/local.propchmod 644 /data/local.propreboot
Koneksi terputus saat reboot, jadi:
adb shellPerintah
ps media sekarang akan menampilkan dua proses:- media.log
- server media
Catat ID proses mediaserver untuk nanti.
Menampilkan garis waktu
Anda dapat meminta dump log secara manual kapan saja. Perintah ini menampilkan log dari semua linimasa aktif dan terkini, lalu menghapusnya:
dumpsys media.log
Perhatikan bahwa garis waktu desain bersifat independen, dan tidak ada fasilitas untuk menggabungkan garis waktu.
Memulihkan log setelah kematian server media
Sekarang coba matikan proses mediaserver : kill -9 # , di mana # adalah ID proses yang Anda catat sebelumnya. Anda akan melihat dump dari media.log di logcat utama , menampilkan semua log yang mengarah ke crash.
dumpsys media.log