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.so
baru ke/system/lib
perangkat.
Pengaturan waktu berjalan
-
adb shell getprop | grep ro.debuggable
Konfirmasikan bahwa outputnya adalah:[ro.debuggable]: [1]
-
adb shell
-
ls -ld /data/misc/audioserver
Konfirmasikan bahwa outputnya adalah:
drwx------ media media ... media
Jika direktori tidak ada, buat sebagai berikut:
mkdir /data/misc/audioserver
chown media:media /data/misc/audioserver
-
echo af.tee=# > /data/local.prop
Di mana nilaiaf.tee
adalah 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
dumpsys
seperti ini:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Ini adalah file .wav PCM. - Kemudian
adb pull
file/data/misc/audioserver/*.wav
yang diinginkan; perhatikan bahwa nama file dump khusus trek tidak muncul di outputdumpsys
, tetapi masih disimpan ke/data/misc/audioserver
setelah 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
dumpsys
segera 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.so
yang dipulihkan ke/system/lib
perangkat. -
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
ALOGV
dinonaktifkan 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
FastMixer
danFastCapture
. - 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
mediaserver
crash 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:
![Arsitektur sebelum media.log](https://source.android.google.cn/static/devices/audio/images/medialog_before.png?hl=id)
Gambar 1. Arsitektur sebelum media.log
Poin penting:
-
init
fork dan execsmediaserver
. -
init
mendeteksi kematianmediaserver
, dan melakukan fork ulang seperlunya. - Pencatatan log
ALOGx
tidak ditampilkan.
Diagram di bawah ini menunjukkan hubungan baru dari komponen, setelah media.log
ditambahkan ke arsitektur:
![Arsitektur setelah media.log](https://source.android.google.cn/static/devices/audio/images/medialog_after.png?hl=id)
Gambar 2. Arsitektur setelah media.log
Perubahan penting:
- Klien menggunakan
NBLOG
API untuk membuat entri log dan menambahkannya ke buffer melingkar di memori bersama. -
MediaLogService
dapat 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 root
adb shell
echo ro.test_harness=1 > /data/local.prop
chmod 644 /data/local.prop
reboot
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