AAudio ve MMAP

AAudio, Android 8.0 sürümünde tanıtılan bir ses API'sidir. Android 8.1 sürümü, bir HAL ve MMAP'ı destekleyen sürücü ile birlikte kullanıldığında gecikmeyi azaltan geliştirmelere sahiptir. Bu belge, Android'de AAudio'nun MMAP özelliğini desteklemek için gereken donanım soyutlama katmanını (HAL) ve sürücü değişikliklerini açıklamaktadır.

AAudio MMAP desteği şunları gerektirir:

  • HAL'ın MMAP yeteneklerini bildirmek
  • HAL'de yeni işlevler uygulamak
  • isteğe bağlı olarak ÖZEL mod arabelleği için özel bir ioctl () uygulama
  • ek bir donanım veri yolu sağlamak
  • MMAP özelliğini etkinleştiren sistem özelliklerini ayarlama

AAudio mimarisi

AAudio , Open SL ES'ye bir alternatif sağlayan yeni bir yerel C API'sidir . Ses akışları oluşturmak için Builder tasarım modeli kullanır.

AAudio, düşük gecikmeli bir veri yolu sağlar. ÖZEL modda, özellik, istemci uygulama kodunun doğrudan ALSA sürücüsüyle paylaşılan bir bellek eşlemeli arabelleğe yazmasına izin verir. SHARED modunda, MMAP arabelleği AudioServer'da çalışan bir mikser tarafından kullanılır. EXCLUSIVE modunda, veriler karıştırıcıyı atladığı için gecikme önemli ölçüde daha azdır.

EXCLUSIVE modunda, hizmet HAL'den MMAP arabelleğini ister ve kaynakları yönetir. MMAP arabelleği NOIRQ modunda çalışıyor, bu nedenle arabelleğe erişimi yönetmek için paylaşılan okuma / yazma sayaçları yok. Bunun yerine, istemci donanımın bir zamanlama modelini korur ve arabelleğin ne zaman okunacağını tahmin eder.

Aşağıdaki şemada, MMAP FIFO üzerinden ALSA sürücüsüne akan Darbe kodu modülasyonu (PCM) verilerini görebiliriz. Zaman damgaları AAudio hizmeti tarafından periyodik olarak istenir ve daha sonra atomik bir mesaj kuyruğu aracılığıyla istemcinin zamanlama modeline aktarılır.

PCM veri akış şeması.
Şekil 1. FIFO'dan ALSA'ya PCM veri akışı

SHARED modunda, bir zamanlama modeli de kullanılır, ancak AAudioService'te yaşar.

Ses yakalama için benzer bir model kullanılır, ancak PCM verileri ters yönde akar.

HAL değişiklikleri

TinyALSA için bakınız:

external/tinyalsa/include/tinyalsa/asoundlib.h
external/tinyalsa/include/tinyalsa/pcm.c
int pcm_start(struct pcm *pcm);
int pcm_stop(struct pcm *pcm);
int pcm_mmap_begin(struct pcm *pcm, void **areas,
           unsigned int *offset,
           unsigned int *frames);
int pcm_get_poll_fd(struct pcm *pcm);
int pcm_mmap_commit(struct pcm *pcm, unsigned int offset,
           unsigned int frames);
int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr,
           struct timespec *tstamp);

Eski HAL için bkz:

hardware/libhardware/include/hardware/audio.h
hardware/qcom/audio/hal/audio_hw.c
int start(const struct audio_stream_out* stream);
int stop(const struct audio_stream_out* stream);
int create_mmap_buffer(const struct audio_stream_out *stream,
                        int32_t min_size_frames,
                        struct audio_mmap_buffer_info *info);
int get_mmap_position(const struct audio_stream_out *stream,
                        struct audio_mmap_position *position);

HIDL audio HAL için:

hardware/interfaces/audio/2.0/IStream.hal
hardware/interfaces/audio/2.0/types.hal
hardware/interfaces/audio/2.0/default/Stream.h
start() generates (Result retval);
stop() generates (Result retval) ;
createMmapBuffer(int32_t minSizeFrames)
       generates (Result retval, MmapBufferInfo info);
getMmapPosition()
       generates (Result retval, MmapPosition position);

MMAP desteği raporlama

"Aaudio.mmap_policy" sistem özelliği 2'ye (AAUDIO_POLICY_AUTO) ayarlanmalıdır, böylece ses çerçevesi MMAP modunun ses HAL tarafından desteklendiğini bilir. (aşağıdaki "AAudio MMAP Veri Yolunu Etkinleştirme" bölümüne bakın.)

audio_policy_configuration.xml dosyası ayrıca MMAP / NO IRQ moduna özgü bir çıktı ve girdi profili içermelidir, böylece Ses İlkesi Yöneticisi, MMAP istemcileri oluşturulduğunda hangi akışın açılacağını bilir:

<mixPort name="mmap_no_irq_out" role="source"
            flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                                samplingRates="48000"
                                channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>

<mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                                samplingRates="48000"
                                channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</mixPort>

Bir MMAP akışını açma ve kapatma

createMmapBuffer(int32_t minSizeFrames)
            generates (Result retval, MmapBufferInfo info);

MMAP akışı Tinyalsa işlevleri çağrılarak açılıp kapatılabilir.

MMAP konumunu sorgulama

Zamanlama Modeline geri aktarılan zaman damgası, bir kare konumu ve nanosaniye cinsinden bir MONOTONIC zaman içerir:

getMmapPosition()
        generates (Result retval, MmapPosition position);

HAL, yeni bir Tinyalsa işlevini arayarak bu bilgileri ALSA sürücüsünden alabilir:

int pcm_mmap_get_hw_ptr(struct pcm* pcm,
                        unsigned int *hw_ptr,
                        struct timespec *tstamp);

Çekirdek değişiklikleri

Sürücüde MMAP / NOIRQ modunu etkinleştirin.

Paylaşılan belleğe, ALSA sürücüsü tarafından oluşturulan bir dosya tanımlayıcısı kullanılarak başvurulur. Dosya tanımlayıcısı bir /dev/snd/ driver dosyasıyla doğrudan ilişkiliyse, AAudio hizmeti tarafından SHARED modunda kullanılabilir. Ancak tanımlayıcı, ÖZEL mod için istemci koduna geçirilemez. /dev/snd/ dosya tanımlayıcısı istemciye çok geniş erişim sağlar, bu nedenle SELinux tarafından engellenir.

ÖZEL modu desteklemek için /dev/snd/ tanımlayıcısını anon_inode:dmabuf dosya tanımlayıcısına dönüştürmek gerekir. SELinux, bu dosya tanımlayıcının istemciye aktarılmasına izin verir. AAudioService tarafından da kullanılabilir.

anon_inode:dmabuf dosya tanımlayıcısı, Android Ion bellek kitaplığı kullanılarak oluşturulabilir.

Ek bilgi için şu harici kaynaklara bakın:

  1. "Android ION bellek ayırıcı" https://lwn.net/Articles/480055/
  2. "Android ION'a genel bakış" https://wiki.linaro.org/BenjaminGaignard/ion
  3. "ION bellek ayırıcısını entegre etme" https://lwn.net/Articles/565469/

AAudio hizmetinin bu anon_inode:dmabuf desteklenip desteklenmediğini anon_inode:dmabuf . Şu anda, bunu yapmanın tek yolu MMAP arabelleğinin boyutunu negatif bir sayı olarak iletmektir, örn. Destekleniyorsa 2048 yerine -2048. Akışı açmak zorunda kalmadan bunu bildirmenin daha iyi bir yolu planlanmıştır.

Ses alt sistemi değişiklikleri

Audio, ses alt sisteminin ses ön ucunda ek bir veri yolu gerektirir, böylece orijinal AudioFlinger yolu ile paralel olarak çalışabilir. Bu eski yol, diğer tüm sistem sesleri ve uygulama sesleri için kullanılır. Bu işlevsellik, bir DSP'deki bir yazılım karıştırıcısı veya SOC'deki bir donanım karıştırıcısı tarafından sağlanabilir.

AAudio MMAP Veri Yolunu Etkinleştirme

AAudio, MMAP desteklenmiyorsa veya bir akışı açamıyorsa eski AudioFlinger veri yolunu kullanacaktır. Dolayısıyla AAudio, MMAP / NOIRQ yolunu desteklemeyen bir ses cihazıyla çalışacaktır.

AAudio için MMAP desteğini test ederken, MMAP veri yolunu gerçekten test edip etmediğinizi veya yalnızca eski veri yolunu test edip etmediğinizi bilmek önemlidir. Aşağıda, belirli veri yollarının nasıl etkinleştirileceği veya zorlanacağı ve bir akış tarafından kullanılan yolun nasıl sorgulanacağı açıklanmaktadır.

Sistem özellikleri

MMAP politikasını sistem özelliklerinden ayarlayabilirsiniz:

  • 1 = AAUDIO_POLICY_NEVER - Yalnızca eski yolu kullanın. MMAP kullanmayı denemeyin bile.
  • 2 = AAUDIO_POLICY_AUTO - MMAP kullanmayı deneyin. Bu başarısız olursa veya mevcut değilse, eski yolu kullanın.
  • 3 = AAUDIO_POLICY_ALWAYS - Yalnızca MMAP yolunu kullanın. Eski yola geri dönmeyin.

Bunlar, Makefile aygıtlarında şu şekilde ayarlanabilir:

# Enable AAudio MMAP/NOIRQ data path.
# 2 is AAUDIO_POLICY_AUTO so it will try MMAP then fallback to Legacy path.
PRODUCT_PROPERTY_OVERRIDES += aaudio.mmap_policy=2
# Allow EXCLUSIVE then fall back to SHARED.
PRODUCT_PROPERTY_OVERRIDES += aaudio.mmap_exclusive_policy=2

Aygıt önyüklendikten sonra da bu değerleri geçersiz kılabilirsiniz. Değişikliğin etkili olması için ses sunucusunu yeniden başlatmanız gerekecek. Örneğin, MMAP için AUTO modunu etkinleştirmek için:

adb root
adb shell setprop aaudio.mmap_policy 2
adb shell killall audioserver

ndk/sysroot/usr/include/aaudio/AAudioTesting.h MMAP yolunu kullanma politikasını geçersiz ndk/sysroot/usr/include/aaudio/AAudioTesting.h izin veren ndk/sysroot/usr/include/aaudio/AAudioTesting.h vardır:

aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy);

Bir akışın MMAP yolunu kullanıp kullanmadığını öğrenmek için şunu arayın:

bool AAudioStream_isMMapUsed(AAudioStream* stream);