Ses Hata Ayıklama

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

  1. cd frameworks/av/services/audioflinger
  2. Configuration.h .
  3. #define TEE_SINK .
  4. libaudioflinger.so yeniden oluşturun.
  5. adb root
  6. adb remount
  7. Yeni libaudioflinger.so aygıtın /system/lib dizinine aktarın veya eşitleyin.

Çalışma zamanı kurulumu

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

  1. Ses testinizi çalıştırın.
  2. adb shell dumpsys media.audio_flinger
  3. 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.
  4. Ardından adb pull , ilgilendiğiniz /data/misc/audioserver/*.wav dosyalarını çekin; parçaya özgü döküm dosya adlarının dumpsys çıktısında görünmediğini, ancak yol kapatıldıktan sonra /data/misc/audioserver kaydedildiğini unutmayın.
  5. 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:

  1. Kaynak kodu değişikliklerini Configuration.h olarak geri alın.
  2. libaudioflinger.so yeniden oluşturun.
  3. Geri yüklenen libaudioflinger.so aygıtın /system/lib dizinine gönderin veya eşitleyin.
  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 __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 ve FastCapture 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:

media.log'dan önceki mimari

Şekil 1. media.log'dan önceki mimari

Önemli noktalar:

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

media.log'dan sonra 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 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