Debug Audio

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

  1. cd frameworks/av/services/audioflinger
  2. Edit Configuration.h .
  3. Batalkan komentar #define TEE_SINK .
  4. Bangun libaudioflinger.so .
  5. adb root
  6. adb remount
  7. Dorong atau sinkronkan libaudioflinger.so baru ke /system/lib perangkat.

Pengaturan waktu berjalan

  1. adb shell getprop | grep ro.debuggable
    Konfirmasikan bahwa outputnya adalah: [ro.debuggable]: [1]
  2. adb shell
  3. 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
    
  4. echo af.tee=# > /data/local.prop
    Di mana nilai af.tee adalah angka yang dijelaskan di bawah ini.
  5. chmod 644 /data/local.prop
  6. 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

  1. Jalankan tes audio Anda.
  2. adb shell dumpsys media.audio_flinger
  3. Cari baris di output dumpsys seperti ini:
    tee copied to /data/misc/audioserver/20131010101147_2.wav
    Ini adalah file .wav PCM.
  4. Kemudian adb pull file /data/misc/audioserver/*.wav yang diinginkan; perhatikan bahwa nama file dump khusus trek tidak muncul di output dumpsys , tetapi masih disimpan ke /data/misc/audioserver setelah trek ditutup.
  5. 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:

  1. Kembalikan perubahan kode sumber ke Configuration.h .
  2. Bangun libaudioflinger.so .
  3. Dorong atau sinkronkan libaudioflinger.so yang dipulihkan ke /system/lib perangkat.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. 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 dan FastCapture .
  • 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

Gambar 1. Arsitektur sebelum media.log

Poin penting:

  • init fork dan execs mediaserver .
  • init mendeteksi kematian mediaserver , 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

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 shell
Perintah 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