Bu makalede, Android sesinde hata ayıklamayla ilgili bazı ipuçları ve püf noktaları açıklanmaktadır.
Lavabo
"Tee sink", yalnızca özel derlemelerde kullanılabilen bir AudioFlinger hata ayıklama özelliğidir. Bu özellik, daha sonra analiz etmek üzere son sesin kısa bir parçasını saklar. Bu sayede, gerçekte oynatılan veya kaydedilen ile beklenen arasında karşılaştırma yapılabilir.
Gizlilik için tee alıcısı hem derleme hem de çalışma zamanında varsayılan olarak devre dışıdır. Tee sink'i kullanmak için yeniden derleyerek ve bir mülk ayarlayarak etkinleştirmeniz gerekir. Hata ayıklama işlemini tamamladıktan sonra bu özelliği devre dışı bıraktığınızdan emin olun. Tee sink, üretim derlemelerinde etkin bırakılmamalıdır.
Bu bölümdeki talimatlar Android 7.x ve sonraki sürümler içindir. Android 5.x ve 6.x için /data/misc/audioserver
ifadesini /data/misc/media
ile değiştirin. Ayrıca, userdebug veya eng derlemesi kullanmanız gerekir. userdebug derlemesi kullanıyorsanız Verity'yi şu şekilde devre dışı bırakın:
adb root && adb disable-verity && adb reboot
Derleme zamanı kurulumu
cd frameworks/av/services/audioflinger
Configuration.h
öğesini düzenleyin.#define TEE_SINK
için yorumu kaldırın.libaudioflinger.so
'ü yeniden oluşturun.adb root
adb remount
- Yeni
libaudioflinger.so
dosyasını cihazın/system/lib
dosyasına gönderin veya senkronize edin.
Çalışma zamanı kurulumu
adb shell getprop | grep ro.debuggable
Çıkışı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ğeri aşağıda açıklanan bir sayıdır.chmod 644 /data/local.prop
reboot
af.tee mülkünün değerleri
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 kısa bir açıklamasını görmek için AudioFlinger.cpp
dosyasının AudioFlinger::AudioFlinger()
satırına bakın:
- 1 = giriş
- 2 = FastMixer çıkışı
- 4 = Parça başına AudioRecord ve AudioTrack
Henüz derin arabelleğe alma veya normal karıştırıcı için bit yok ancak "4" değerini kullanarak benzer sonuçlar elde edebilirsiniz.
Verileri test etme ve edinme
- Ses testinizi çalıştırın.
adb shell dumpsys media.audio_flinger
dumpsys
çıkışında şuna benzer bir satır arayın:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Bu bir PCM .wav dosyasıdır.- Ardından, ilgilendiğiniz
adb pull
/data/misc/audioserver/*.wav
dosyaları; kanala özgü dökümü dosya adlarınındumpsys
çıkışında görünmediğini ancak kanal kapatıldığında/data/misc/audioserver
'a kaydedilmeye devam ettiğini unutmayın. - Başkalarıyla paylaşmadan önce gizlilik sorunları açısından döküm dosyalarını inceleyin.
Öneriler
Daha faydalı sonuçlar için aşağıdaki fikirleri deneyin:
- Test çıkışındaki kesintileri azaltmak için dokunma seslerini ve tuş tıklamalarını devre dışı bırakın.
- Tüm sesleri en üst düzeye çıkarın.
- Testinizle ilgili olmayan, ses çıkaran veya mikrofondan kayıt yapan uygulamaları devre dışı bırakın.
- Parçaya özgü dökümler yalnızca parça kapatıldığında kaydedilir. Parçaya özgü verilerini dökmek için bir uygulamayı zorla kapatmanız gerekebilir.
dumpsys
işlemini testten hemen sonra yapın. Kayıt alanı sınırlıdır.- Döküm dosyalarınızı kaybetmemek için düzenli olarak barındırıcınıza yükleyin. Yalnızca sınırlı sayıda dökümü dosya saklanır. Bu sınıra ulaşıldığında eski dökümler kaldırılır.
Geri yükle
Yukarıda belirtildiği gibi, T lavabo özelliği etkin bırakılmamalıdır. Derlemenizi ve cihazınızı aşağıdaki gibi geri yükleyin:
- Kaynak kodundaki değişiklikleri
Configuration.h
olarak geri alın. libaudioflinger.so
'ü yeniden oluşturun.- Restore edilen
libaudioflinger.so
'yi cihazın/system/lib
ile senkronize edin veya cihaza gönderin. adb shell
rm /data/local.prop
rm /data/misc/audioserver/*.wav
reboot
media.log
ALOGx makroları
Android SDK'sındaki standart Java dili günlük kaydı API'si android.util.Log'dur.
Android NDK'daki ilgili C dili API'si __android_log_print
<android/log.h>
içinde tanımlanmıştır.
Android çerçevesinin yerel bölümünde ALOGE
, ALOGW
, ALOGI
, ALOGV
vb. adlı makroları tercih ederiz. Bunlar <utils/Log.h>
içinde tanımlanır ve bu makale kapsamında toplu olarak ALOGx
olarak adlandırılır.
Bu API'lerin tümü kullanımı kolay ve iyi anlaşılır olduğu için Android platformunda yaygın olarak kullanılır. Özellikle AudioFlinger ses sunucusunu içeren mediaserver
işlemi, ALOGx
'yi yoğun şekilde kullanır.
Bununla birlikte, ALOGx
ve arkadaşlarla ilgili bazı sınırlamalar vardır:
-
"Günlük spam'ine" karşı hassastırlar: Günlük arabelleği paylaşılan bir kaynak olduğundan, alakasız günlük girişleri nedeniyle kolayca taşabilir ve bu da bilgilerin kaçırılmasına neden olabilir.
ALOGV
varyantı varsayılan olarak derleme zamanında devre dışıdır. Ancak etkinleştirilirse günlük spam'e neden olabilir. -
Temel çekirdek sistem çağrıları engellenebilir. Bu da öncelik tersine çevrilmesine ve dolayısıyla ölçüm kesintilerine ve yanlışlıklarına neden olabilir. Bu durum,
FastMixer
veFastCapture
gibi zaman açısından kritik olan mesaj dizileri için özellikle önemlidir. - Günlük spam'ini azaltmak için belirli bir günlük devre dışı bırakılırsa bu günlük tarafından yakalanacak tüm bilgiler kaybolur. Belirli bir günlüğün ilgi çekici olduğu anlaşıldıktan sonra 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 ile MediaLogService
hizmeti birlikte medya için daha yeni bir günlük kaydı sistemi oluşturur ve özellikle yukarıdaki sorunları gidermek için tasarlanmıştır. Üçünü de belirtmek için "media.log" terimini gevşek bir şekilde kullanacağız ancak 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 kullanılan bir Android bağlayıcı hizmetidir.
media.log
"zaman çizelgesi", göreceli sıralaması korunan bir günlük girişi dizisidir.
Her ileti dizisinin kendi zaman çizelgesini kullanması gerekir.
Avantajlar
media.log
sisteminin avantajları şunlardır:
- Gerekmediği sürece ana günlükte spam oluşturmaz.
mediaserver
kilitlendiğinde veya donduğunda bile incelenebilir.- Zaman çizelgesi başına engelleme yapmaz.
- Performans üzerinde daha az etki sunar. (Elbette hiçbir günlük kaydı şekli tamamen rahatsız edici değildir.)
Mimari
Aşağıdaki şemada, media.log
kullanılmadan önce mediaserver
sürecinin init
süreciyle ilişkisi gösterilmektedir:

Şekil 1. media.log öncesi mimari
Önemli noktalar:
init
forks ve execsmediaserver
.init
,mediaserver
'un sona erdiğini algılar ve gerekirse yeniden çatallanır.ALOGx
günlük kaydı gösterilmiyor.
Aşağıdaki şemada, media.log
mimariye eklendikten sonra bileşenlerin yeni ilişkisi gösterilmektedir:

Şekil 2. media.log'dan sonra 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'yi kullanır. -
MediaLogService
, dairesel arabelleğin içeriğini dilediğinde dökebilir. -
Dairesel tampon, paylaşılan bellekte bozulma olması durumunda
MediaLogService
'ün kilitlenmemesi ve bozulmadan etkilenmeyen tamponun bir kısmını yine de dökmeye devam edebilmesi için tasarlanmıştır. - Dairesel arabellek, hem yeni girişler yazmak hem de mevcut girişleri okumak için engellenmez ve kilitlenmez.
- Dairesel arabelleğe yazmak veya bu arabellekten okumak için çekirdek sistem çağrısı gerekmez (isteğe bağlı zaman damgalarından başka).
Kullanım yeri
Android 4.4'ten itibaren AudioFlinger'da media.log
sistemini kullanan yalnızca birkaç günlük noktası vardır. Yeni API'lerin kullanımı ALOGx
kadar kolay olmasa da çok da zor değildir.
Yeni günlük kaydı sistemini, gerekli olduğu durumlarda kullanmanızı öneririz.
Özellikle, FastMixer
ve FastCapture
gibi sık, düzenli olarak ve engellemeden çalışması gereken AudioFlinger iş parçacıkları için önerilir.
Nasıl kullanılır?
Günlük ekleme
Öncelikle kodunuza günlükler eklemeniz gerekir.
FastMixer
ve FastCapture
mesaj dizilerinde aşağıdaki gibi bir kod kullanın:
logWriter->log("string"); logWriter->logf("format", parameters); logWriter->logTimestamp();
Bu NBLog
zaman çizelgesi yalnızca FastMixer
ve FastCapture
ileti dizileri tarafından kullanıldığı için birbirini hariç tutma işlemine gerek yoktur.
Diğer AudioFlinger mesaj dizilerinde mNBLogWriter
kullanın:
mNBLogWriter->log("string"); mNBLogWriter->logf("format", parameters); mNBLogWriter->logTimestamp();
FastMixer
ve FastCapture
dışındaki mesaj dizileri için mesaj dizisinin NBLog
zaman çizelgesi hem mesaj dizisi hem de bağlayıcı işlemleri tarafından kullanılabilir. NBLog::Writer
, zaman çizelgesi başına herhangi bir gizli karşılıklı hariç tutma sağlamaz. Bu nedenle, tüm günlüklerin iş parçacığının mLock
mutex'inin tutulduğu bir bağlamda gerçekleştiğinden emin olun.
Günlükleri ekledikten sonra AudioFlinger'ı yeniden derleyin.
Dikkat:
Zaman çizelgeleri tasarım gereği kilitli mülkleri atladığından, zaman çizelgesi güvenliğini sağlamak için her iş parçacığı için ayrı bir NBLog::Writer
zaman çizelgesi gerekir. Birden fazla iş parçacığının aynı zaman çizelgesini kullanmasını istiyorsanız mevcut bir mutex ile koruyabilirsiniz (mLock
için yukarıda açıklandığı gibi). Alternatif olarak, NBLog::Writer
yerine NBLog::LockedWriter
sarmalayıcısını kullanabilirsiniz.
Ancak bu, bu API'nin en önemli avantajını (engellemesiz davranışı) ortadan kaldırır.
NBLog
API'sinin tamamını frameworks/av/include/media/nbaio/NBLog.h
adresinde bulabilirsiniz.
media.log dosyasını etkinleştirme
media.log
varsayılan olarak devre dışıdır. Yalnızca ro.test_harness
mülkü 1
olduğunda etkindir. Bu özelliği şu şekilde 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 artık iki işlem gösterir:
- media.log
- mediaserver
mediaserver
işleminin kimliğini daha sonra kullanmak üzere not edin.
Zaman çizelgelerini görüntüleme
Dilediğiniz zaman manuel olarak günlük dökümü isteğinde bulunabilirsiniz. Bu komut, etkin ve son zaman çizelgelerindeki günlükleri gösterir ve ardından temizler:
dumpsys media.log
Zaman çizelgelerinin tasarım gereği bağımsız olduğunu ve zaman çizelgelerini birleştirme olanağı olmadığını unutmayın.
Mediaserver'ın kapanmasından sonra günlükleri kurtarma
Şimdi mediaserver
işlemini sonlandırmayı deneyin: kill -9 #
. #, daha önce not ettiğiniz işlem kimliğidir. Ana logcat
bölümünde, kilitlenmeye yol açan tüm günlükleri gösteren media.log
dump dosyasını görürsünüz.
dumpsys media.log