Ses hata ayıklaması

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

  1. cd frameworks/av/services/audioflinger
  2. Configuration.h .
  3. #define TEE_SINK yorumunu kaldırın.
  4. libaudioflinger.so yeniden oluşturun.
  5. adb root
  6. adb remount
  7. Yeni libaudioflinger.so dosyasını cihazın /system/lib dosyasına aktarın veya senkronize edin.

Çalışma zamanı kurulumu

  1. adb shell getprop | grep ro.debuggable
    Çıktının şöyle olduğunu doğrulayın: [ro.debuggable]: [1]
  2. adb shell
  3. 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
    
  4. echo af.tee=# > /data/local.prop
    af.tee değerinin aşağıda açıklanan bir sayı olduğu yer.
  5. chmod 644 /data/local.prop
  6. 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

  1. Ses testinizi çalıştırın.
  2. adb shell dumpsys media.audio_flinger
  3. 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.
  4. Daha sonra adb pull ilgilenilen herhangi bir /data/misc/audioserver/*.wav dosyasını çeker; Parçaya özgü döküm dosya adlarının dumpsys çıktısında görünmediğini, ancak parça kapatıldığında hala /data/misc/audioserver kaydedildiğini unutmayın.
  5. 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:

  1. Kaynak kodu değişikliklerini Configuration.h olarak geri alın.
  2. libaudioflinger.so yeniden oluşturun.
  3. Geri yüklenen libaudioflinger.so dosyasını cihazın /system/lib dosyasına aktarın veya senkronize edin.
  4. adb shell
  5. rm /data/local.prop
  6. rm /data/misc/audioserver/*.wav
  7. 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 ve FastCapture 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:

Media.log'dan önceki mimari

Şekil 1. Media.log öncesi mimari

Dikkate değer noktalar:

  • init çatalları ve mediaserver ç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:

Media.log'dan sonraki mimari

Ş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 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