Bu makalede Android ses hatalarını ayıklamaya yönelik bazı ipuçları ve püf noktaları açıklanmaktadır.
Tişört lavabo
"Tee lavabo", daha sonra analiz edilmek üzere en son sesin kısa bir parçasını saklamak için yalnızca özel yapılarda mevcut olan bir AudioFlinger hata ayıklama özelliğidir. Bu, gerçekte oynatılan veya kaydedilen ile beklenen arasında karşılaştırma yapılmasına olanak tanır.
Gizlilik nedeniyle, tee havuzu hem derleme zamanında hem de çalışma zamanında varsayılan olarak devre dışıdır. Tişört lavabosunu kullanmak için, yeniden derleyerek ve ayrıca bir özellik ayarlayarak onu etkinleştirmeniz gerekecektir. Hata ayıklamayı tamamladıktan sonra bu özelliği devre dışı bıraktığınızdan emin olun; üretim yapılarında tişört lavabosu etkin bırakılmamalıdır.
Bu bölümdeki talimatlar Android 7.x ve üzeri 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 kullanıcı hata ayıklama yapısı kullanıyorsanız, doğrulamayı şununla 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
yorumunu kaldırın. -
libaudioflinger.so
yeniden oluşturun. -
adb root
-
adb remount
- Yeni
libaudioflinger.so
dosyasını cihazın/system/lib
dosyasına aktarın veya senkronize edin.
Çalışma zamanı kurulumu
-
adb shell getprop | grep ro.debuggable
Çıktının şöyle olduğunu doğrulayın:[ro.debuggable]: [1]
-
adb shell
-
ls -ld /data/misc/audioserver
Çıktının şöyle olduğunu doğrulayın:
drwx------ media media ... media
Dizin mevcut değilse aşağıdaki şekilde 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 yer. -
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
dosyasındaki AudioFlinger::AudioFlinger()
koduna bakın, ancak kısaca:
- 1 = giriş
- 2 = FastMixer çıkışı
- 4 = parça başına AudioRecord ve AudioTrack
Henüz derin tampon veya normal karıştırıcı için bir bit yok, ancak "4" kullanarak da benzer sonuçlar elde edebilirsiniz.
Verileri test edin ve edinin
- Ses testinizi çalıştırın.
-
adb shell dumpsys media.audio_flinger
-
dumpsys
çıktısında şöyle bir satır arayın:
tee copied to /data/misc/audioserver/20131010101147_2.wav
Bu bir PCM .wav dosyasıdır. - Daha sonra
adb pull
ilgilenilen herhangi bir/data/misc/audioserver/*.wav
dosyasını çeker; Parçaya özgü döküm dosya adlarınındumpsys
çıktısında görünmediğini, ancak parça kapatıldığında hala/data/misc/audioserver
kaydedildiğini unutmayın. - Başkalarıyla paylaşmadan önce döküm dosyalarını gizlilik sorunları açısından inceleyin.
Öneriler
Daha yararlı sonuçlar için bu fikirleri deneyin:
- Test çıkışındaki kesintileri azaltmak için dokunma seslerini ve tuş tıklamalarını devre dışı bırakın.
- Tüm hacimleri maksimuma çıkarın.
- Testiniz ilginizi çekmiyorsa ses çıkaran veya mikrofondan kayıt yapan uygulamaları devre dışı bırakın.
- Parçaya özel dökümler yalnızca parça kapatıldığında kaydedilir; Parçaya özgü verileri boşaltmak için bir uygulamayı kapatmaya zorlamanız gerekebilir
-
dumpsys
testten 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 şekilde geri yükleyin:
- Kaynak kodu değişikliklerini
Configuration.h
olarak geri alın. -
libaudioflinger.so
yeniden oluşturun. - Geri yüklenen
libaudioflinger.so
dosyasını cihazın/system/lib
dosyasına aktarın veya senkronize edin. -
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 NDK'daki karşılık gelen C dili API'si <android/log.h>
içinde bildirilen __android_log_print
.
Android çerçevesinin yerel kısmında ALOGE
, ALOGW
, ALOGI
, ALOGV
vb. adlı makroları tercih ederiz. Bunlar <utils/Log.h>
dosyasında bildirilir ve bu makalenin amaçları doğrultusunda bunlara toplu olarak ALOGx
olarak değineceğiz. .
Tüm bu API'lerin kullanımı kolay ve iyi anlaşılmıştır, dolayısıyla Android platformunda yaygındırlar. Özellikle AudioFlinger ses sunucusunu içeren mediaserver
işlemi ALOGx
yoğun bir şekilde kullanır.
Bununla birlikte ALOGx
ve arkadaşlarına yönelik bazı sınırlamalar vardır:
- "Günlük spam'ına" karşı hassastırlar: Günlük arabelleği paylaşılan bir kaynaktır, dolayısıyla ilgisiz günlük girişleri nedeniyle kolayca taşabilir ve bu da bilgilerin kaçırılmasına neden olabilir.
ALOGV
değişkeni derleme zamanında varsayılan olarak devre dışıdır. Ancak elbette, eğer etkinleştirilirse, günlük spam'ına da neden olabilir. - Temel çekirdek sistemi çağrıları bloke olabilir, bu da muhtemelen önceliklerin tersine çevrilmesine ve sonuç olarak ölçüm bozukluklarına ve yanlışlıklara yol açabilir. Bu,
FastMixer
veFastCapture
gibi zaman açısından kritik iş parçacıkları için özellikle önemlidir. - 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 yakalanacak tüm bilgiler kaybolur. Günlüğün ilgi çekici olacağı netleştikten sonra belirli bir günlüğün geriye dönük olarak etkinleştirilmesi mümkün değildir.
NBLOG, media.log ve MediaLogService
NBLOG
API'leri ve ilgili media.log
süreci 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. Üçünü de belirtmek için genel olarak "media.log" terimini kullanacağız, ancak kesin olarak konuşursak NBLOG
, C++ günlük API'sidir, media.log
bir Linux işlem adıdır ve MediaLogService
, günlükleri incelemek için bir Android ciltleme hizmetidir.
media.log
"zaman çizelgesi", göreceli sıralaması korunan bir dizi günlük girişidir. Geleneksel olarak her iş parçacığının kendi zaman çizelgesini kullanması gerekir.
Faydalar
media.log
sisteminin faydaları şunlardır:
- Gerekmedikçe ve gerekmedikçe ana günlüğü spamlamaz.
-
mediaserver
çöktüğünde veya kilitlendiğinde bile incelenebilir. - Zaman çizelgesi başına engellemez.
- Performansa daha az rahatsızlık verir. (Elbette hiçbir kayıt şekli tamamen müdahaleci değildir.)
Mimari
Aşağıdaki şema, media.log
tanıtılmadan önce mediaserver
işlemi ile init
işleminin ilişkisini göstermektedir:
Dikkate değer noktalar:
-
init
çatalları vemediaserver
çalıştırır. -
init
,mediaserver
ölümünü algılar ve gerektiği şekilde yeniden çatallanır. -
ALOGx
günlüğü gösterilmiyor.
Aşağıdaki diyagram, media.log
mimariye eklendikten sonra bileşenlerin yeni ilişkisini göstermektedir:
Önemli değişiklikler:
- İstemciler, günlük girişleri oluşturmak ve bunları paylaşılan bellekteki dairesel bir ara belleğe eklemek için
NBLOG
API'yi kullanır. -
MediaLogService
dairesel arabelleğin içeriğini herhangi bir zamanda boşaltabilir. - Dairesel arabellek, paylaşılan bellekteki herhangi bir bozulmanın
MediaLogService
çökertmeyeceği ve yine de bozulmadan etkilenmeyen arabelleğin büyük bir kısmını boşaltabilecek şekilde tasarlanmıştır. - Dairesel arabellek, hem yeni girişlerin yazılması hem de mevcut girişlerin okunması için engellenmez ve kilitlenmez.
- Döngüsel ara belleğe yazmak veya buradan okumak için (isteğe bağlı zaman damgaları dışında) hiçbir çekirdek sistemi çağrısına gerek yoktur.
Nerede kullanılır
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ğil. Vazgeçilmez olduğu durumlar için yeni kayıt sistemini öğrenmenizi öneririz. Özellikle FastMixer
ve FastCapture
iş parçacıkları gibi sık sık, periyodik olarak ve engelleme olmadan çalışması gereken AudioFlinger iş parçacıkları için önerilir.
Nasıl kullanılır
Günlük ekle
Öncelikle kodunuza günlükleri eklemeniz gerekir.
FastMixer
ve FastCapture
iş parçacıklarında ş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ı hariç tutmaya gerek yoktur.
Diğer AudioFlinger başlıklarında 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 ciltleyici 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 mutex mLock
tutulduğu bir bağlamda oluştuğundan emin olun.
Günlükleri ekledikten sonra AudioFlinger'ı yeniden oluşturun.
Dikkat: Zaman çizelgeleri tasarım gereği muteksleri çıkardığından, iş parçacığı güvenliğini sağlamak için iş parçacığı başına ayrı bir NBLog::Writer
zaman çizelgesi gerekir. 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 NBLog::Writer
yerine NBLog::LockedWriter
sarmalayıcısını kullanabilirsiniz. Ancak bu, bu API'nin en önemli avantajını ortadan kaldırır: engellememe davranışı.
Tam NBLog
API'si frameworks/av/include/media/nbaio/NBLog.h
adresindedir.
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. Bunu ş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 şimdi iki işlemi gösterecek:- medya.log
- medya sunucusu
Daha sonra kullanmak üzere mediaserver
işlem kimliğini not edin.
Zaman çizelgelerini göster
Günlük dökümünü istediğiniz zaman manuel olarak talep edebilirsiniz. Bu komut, tüm etkin ve son zaman çizelgelerindeki 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ğının bulunmadığını unutmayın.
Medya sunucusu ölümünden sonra günlükleri kurtarın
Şimdi mediaserver
sürecini öldürmeyi deneyin: kill -9 #
, burada # daha önce not ettiğiniz işlem kimliğidir. Ana logcat
dosyasında media.log
, çökmeye yol açan tüm günlükleri gösteren bir döküm görmelisiniz.
dumpsys media.log