Bu makalede, Android sesinde hata ayıklamaya yönelik bazı ipuçları ve püf noktaları açıklanmaktadır.
Tee Lavabo
"Tee havuzu", daha sonra analiz için en son sesin kısa bir parçasını tutmak için yalnızca özel yapılarda bulunan bir AudioFlinger hata ayıklama özelliğidir. Bu, gerçekte çalınan veya kaydedilenler ile beklenenler arasında karşılaştırmaya izin verir.
Gizlilik için tee havuzu, hem derleme zamanında hem de çalışma zamanında varsayılan olarak devre dışıdır. Tee havuzunu kullanmak için, yeniden derleyerek ve ayrıca bir özellik ayarlayarak etkinleştirmeniz gerekir. Hata ayıklamayı bitirdikten sonra bu özelliği devre dışı bıraktığınızdan emin olun; üretim yapılarında tee lavabo etkin bırakılmamalıdır.
Bu bölümdeki talimatlar Android 7.x ve üstü içindir. Android 5.x ve 6.x için /data/misc/audioserver
/data/misc/media
ile değiştirin. Ek olarak, bir userdebug veya eng build kullanmanız gerekir. Bir userdebug derlemesi kullanıyorsanız, aşağıdakilerle gerçekliği devre dışı bırakın:
adb root && adb disable-verity && adb reboot
Derleme zamanı kurulumu
-
cd frameworks/av/services/audioflinger
-
Configuration.h
. -
#define TEE_SINK
. -
libaudioflinger.so
yeniden oluşturun. -
adb root
-
adb remount
- Yeni
libaudioflinger.so
aygıtın/system/lib
dizinine aktarın veya eşitleyin.
Çalışma zamanı kurulumu
-
adb shell getprop | grep ro.debuggable
Çıktının şu şekilde olduğunu onaylayın:[ro.debuggable]: [1]
-
adb shell
-
ls -ld /data/misc/audioserver
Çıktının şu şekilde olduğunu onaylayın:
drwx------ media media ... media
Dizin yoksa, aşağıdaki gibi oluşturun:
mkdir /data/misc/audioserver
chown media:media /data/misc/audioserver
-
echo af.tee=# > /data/local.prop
af.tee
değerinin aşağıda açıklanan bir sayı olduğu durumlarda. -
chmod 644 /data/local.prop
-
reboot
af.tee
özelliği için değerler
af.tee
değeri, özellik başına bir tane olmak üzere birkaç bitin toplamını ifade eden 0 ile 7 arasında bir sayıdır. Her bitin açıklaması için AudioFlinger.cpp içindeki AudioFlinger.cpp
AudioFlinger::AudioFlinger()
adresindeki koda bakın, ancak kısaca:
- 1 = giriş
- 2 = FastMixer çıkışı
- 4 = parça başına AudioRecord ve AudioTrack
Henüz derin arabellek veya normal karıştırıcı için bit yok, ancak "4" kullanarak benzer sonuçlar elde edebilirsiniz.
Verileri test edin ve alın
- Ses testinizi çalıştırın.
-
adb shell dumpsys media.audio_flinger
-
dumpsys
çıktısında aşağıdaki gibi bir satır arayın:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Bu bir PCM .wav dosyasıdır. - Ardından
adb pull
, ilgilendiğiniz/data/misc/audioserver/*.wav
dosyalarını çekin; parçaya özgü döküm dosya adlarınındumpsys
çıktısında görünmediğini, ancak yol kapatıldıktan sonra/data/misc/audioserver
kaydedildiğini unutmayın. - Başkalarıyla paylaşmadan önce döküm dosyalarını gizlilik endişeleri açısından inceleyin.
Öneriler
Daha faydalı sonuçlar için şu fikirleri deneyin:
- Test çıkışındaki kesintileri azaltmak için dokunma seslerini ve tuş tıklamalarını devre dışı bırakın.
- Tüm hacimleri en üst düzeye çıkarın.
- Testinizle ilgilenmiyorlarsa, mikrofondan ses çıkaran veya kayıt yapan uygulamaları devre dışı bırakın.
- Güzergaha özgü dökümler yalnızca hat kapatıldığında kaydedilir; parçaya özel verilerini boşaltmak için bir uygulamayı kapatmaya zorlamanız gerekebilir
-
dumpsys
hemen sonra yapın; sınırlı miktarda kayıt alanı mevcuttur. - Döküm dosyalarınızı kaybetmediğinizden emin olmak için bunları düzenli aralıklarla ana makinenize yükleyin. Yalnızca sınırlı sayıda döküm dosyası korunur; bu sınıra ulaşıldıktan sonra eski dökümler kaldırılır.
Eski haline getirmek
Yukarıda belirtildiği gibi, tişört lavabo özelliği etkin bırakılmamalıdır. Yapınızı ve cihazınızı aşağıdaki gibi geri yükleyin:
- Kaynak kodu değişikliklerini
Configuration.h
olarak geri alın. -
libaudioflinger.so
yeniden oluşturun. - Geri yüklenen
libaudioflinger.so
aygıtın/system/lib
dizinine gönderin veya eşitleyin. -
adb shell
-
rm /data/local.prop
-
rm /data/misc/audioserver/*.wav
-
reboot
medya.log
ALOGx makroları
Android SDK'daki standart Java dili günlük kaydı API'si android.util.Log'dur .
Android __android_log_print
ilgili C dili API'si, <android/log.h>
içinde bildirilen __android_log_print'tir.
Android çerçevesinin yerel bölümünde, ALOGE
, ALOGW
, ALOGI
, ALOGV
, vb. adlı makroları tercih ederiz. Bunlar <utils/Log.h>
içinde bildirilir ve bu makalenin amaçları doğrultusunda topluca ALOGx
olarak bahsedeceğiz. .
Tüm bu API'lerin kullanımı kolaydır ve iyi anlaşılır, bu nedenle Android platformunda yaygındırlar. Özellikle mediaserver
ses sunucusunu içeren medya sunucusu işlemi, ALOGx
yoğun bir şekilde kullanır.
Yine de, ALOGx
ve arkadaşları için bazı sınırlamalar vardır:
- "Spam günlüğüne" duyarlıdırlar: günlük arabelleği paylaşılan bir kaynaktır, bu nedenle alakasız günlük girişleri nedeniyle kolayca taşabilir ve bu da bilgilerin kaçırılmasına neden olur.
ALOGV
varyantı derleme zamanında varsayılan olarak devre dışıdır. Ancak, etkinleştirilirse, elbette, günlük spam'ine neden olabilir. - Temeldeki çekirdek sistem çağrıları bloke olabilir, bu da muhtemelen önceliğin tersine çevrilmesine ve sonuç olarak ölçüm bozukluklarına ve yanlışlıklara neden olabilir. Bu,
FastMixer
veFastCapture
gibi zaman açısından kritik iş parçacıkları için özel bir endişe kaynağıdır. - Günlük spam'ini azaltmak için belirli bir günlük devre dışı bırakılırsa, o günlük tarafından yakalanmış olabilecek tüm bilgiler kaybolur. Günlüğün ilginç olacağı netleştikten sonra , belirli bir günlüğü geriye dönük olarak etkinleştirmek mümkün değildir.
NBLOG, media.log ve MediaLogService
NBLOG
API'leri ve ilişkili media.log
işlemi ve MediaLogService
hizmeti birlikte medya için daha yeni bir günlük kaydı sistemi oluşturur ve özellikle yukarıdaki sorunları çözmek için tasarlanmıştır. Üçüne de atıfta bulunmak için "media.log" terimini gevşek bir şekilde kullanacağız, ancak açıkçası NBLOG
, C++ günlük kaydı API'sidir, media.log
bir Linux işlem adıdır ve MediaLogService
, günlükleri incelemek için bir Android bağlayıcı hizmetidir.
media.log
"zaman çizelgesi", göreli sıralaması korunan bir dizi günlük girişidir. Geleneksel olarak, her iş parçacığı kendi zaman çizelgesini kullanmalıdır.
Faydalar
media.log
sisteminin faydaları şudur:
- Ana günlüğü gerekmedikçe ve gerekmedikçe spam göndermez.
-
mediaserver
çöktüğünde veya kilitlendiğinde bile incelenebilir. - Zaman çizelgesi başına engelleme yapmıyor.
- Performansa daha az rahatsızlık verir. (Elbette hiçbir günlük kaydı biçimi tamamen müdahaleci değildir.)
Mimari
Aşağıdaki diyagram, media.log
mediaserver
ile init
işleminin ilişkisini gösterir:

Şekil 1. media.log'dan önceki mimari
Önemli noktalar:
-
init
çatallar vemediaserver
. -
init
,mediaserver
ölümünü algılar ve gerektiğinde yeniden çatallar. -
ALOGx
günlüğü gösterilmez.
Aşağıdaki şema, mimariye media.log
eklendikten sonra bileşenlerin yeni ilişkisini göstermektedir:

Şekil 2. media.log'dan sonraki mimari
Önemli değişiklikler:
- İstemciler, günlük girişleri oluşturmak ve bunları paylaşılan bellekteki dairesel bir arabelleğe eklemek için
NBLOG
API'sini kullanır. -
MediaLogService
, dairesel arabelleğin içeriğini herhangi bir zamanda boşaltabilir. - Dairesel arabellek, paylaşılan bellekteki herhangi bir bozulmanın
MediaLogService
çökmesine neden olmayacağı şekilde tasarlanmıştır ve yine de bozulmadan etkilenmeyen arabelleğin çoğunu boşaltabilecektir. - Dairesel arabellek, hem yeni girişler yazmak hem de mevcut girişleri okumak için bloke edici ve kilitsizdir.
- Dairesel arabelleğe yazmak veya buradan okumak için çekirdek sistem çağrısı gerekmez (isteğe bağlı zaman damgaları dışında).
Nerede kullanılır
Android 4.4'ten itibaren media.log
sistemini kullanan yalnızca birkaç günlük noktası vardır. Yeni API'lerin kullanımı ALOGx
kadar kolay olmasa da aşırı zor da değiller. Vazgeçilmez olduğu durumlar için yeni kayıt sistemini öğrenmenizi öneririz. Özellikle, FastMixer
ve FastCapture
dizileri gibi sık sık, periyodik olarak ve engellemeden çalışması gereken AudioFlinger dizileri için önerilir.
Nasıl kullanılır
Günlük ekle
İlk olarak, kodunuza günlükler eklemeniz gerekir.
FastMixer
ve FastCapture
dizilerinde şuna benzer bir kod kullanın:
logWriter->log("string"); logWriter->logf("format", parameters); logWriter->logTimestamp();
Bu NBLog
zaman çizelgesi yalnızca FastMixer
ve FastCapture
iş parçacıkları tarafından kullanıldığından, karşılıklı dışlamaya gerek yoktur.
Diğer AudioFlinger dizilerinde mNBLogWriter
kullanın:
mNBLogWriter->log("string"); mNBLogWriter->logf("format", parameters); mNBLogWriter->logTimestamp();
FastMixer
ve FastCapture
dışındaki iş parçacıkları için, iş parçacığının NBLog
zaman çizelgesi hem iş parçacığının kendisi hem de ciltleme işlemleri tarafından kullanılabilir. NBLog::Writer
, zaman çizelgesi başına herhangi bir örtülü karşılıklı dışlama sağlamaz, bu nedenle tüm günlüklerin, iş parçacığının muteks mLock
tutulduğu bir bağlamda gerçekleştiğinden emin olun.
Günlükleri ekledikten sonra AudioFlinger'ı yeniden oluşturun.
Dikkat: Zaman çizelgeleri tasarım gereği muteksleri içermediğinden, iş parçacığı güvenliğini sağlamak için iş parçacığı başına ayrı bir NBLog::Writer
zaman çizelgesi gereklidir. Birden fazla iş parçacığının aynı zaman çizelgesini kullanmasını istiyorsanız, mevcut bir muteks ile koruma sağlayabilirsiniz (yukarıda mLock
için açıklandığı gibi). Veya NBLog::Writer
yerine NBLog::LockedWriter
sarmalayıcısını kullanabilirsiniz. Ancak bu, bu API'nin başlıca avantajını ortadan kaldırır: engellemeyen davranışı.
Tam NBLog
API, frameworks/av/include/media/nbaio/NBLog.h
.
media.log'u etkinleştir
media.log
varsayılan olarak devre dışıdır. Yalnızca ro.test_harness
özelliği 1
olduğunda etkindir. Şunları yaparak etkinleştirebilirsiniz:
adb root
adb shell
echo ro.test_harness=1 > /data/local.prop
chmod 644 /data/local.prop
reboot
Yeniden başlatma sırasında bağlantı kesilir, bu nedenle:
adb shell
ps media
komutu şimdi iki işlem gösterecek:- medya.log
- medya sunucusu
mediaserver
işlem kimliğini daha sonra not edin.
Zaman çizelgelerini görüntüleme
Dilediğiniz zaman manuel olarak günlük dökümü talep edebilirsiniz. Bu komut, tüm etkin ve son zaman çizelgelerinden günlükleri gösterir ve ardından bunları temizler:
dumpsys media.log
Tasarım gereği zaman çizelgelerinin bağımsız olduğunu ve zaman çizelgelerini birleştirme olanağı bulunmadığını unutmayın.
Mediaserver'ın ölümünden sonra günlükleri kurtarma
Şimdi mediaserver
işlemini öldürmeyi deneyin: kill -9 #
, burada # daha önce not ettiğiniz işlem kimliğidir. Ana logcat
, çökmeye neden olan tüm günlükleri gösteren media.log
bir döküm görmelisiniz.
dumpsys media.log