AAudio, Android 8.0 sürümünde kullanıma sunulan bir ses API'sidir. Android 8.1 sürümünde, MMAP'yi destekleyen bir HAL ve sürücüyle birlikte kullanıldığında gecikmeyi azaltan geliştirmeler vardır. Bu dokümanda, Android'de AAudio'nun MMAP özelliğini desteklemek için gereken donanım soyutlama katmanı (HAL) ve sürücü değişiklikleri açıklanmaktadır.
AAudio MMAP desteği için gerekenler:
- HAL'ın MMAP özelliklerini bildirme
- HAL'de yeni işlevler uygulama
- isteğe bağlı olarak EXCLUSIVE modu arabelleği için özel bir ioctl() uygulama
- ek bir donanım veri yolu sağlayarak
- MMAP özelliğini etkinleştiren sistem özelliklerini ayarlama
AAudio mimarisi
AAudio, Open SL ES'e alternatif sağlayan yeni bir yerel C API'sidir. Ses akışları oluşturmak için bir Oluşturucu tasarım kalıbı kullanır.
AAudio, düşük gecikmeli bir veri yolu sağlar. EXCLUSIVE modunda bu özellik, istemci uygulama kodunun doğrudan ALSA sürücüsüyle paylaşılan bir bellek haritalı arabelleğe yazmasına olanak tanır. SHARED modunda MMAP arabelleği, AudioServer'da çalışan bir karıştırıcı 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ıştığından arabelleğe erişimi yönetmek için paylaşılan okuma/yazma sayaçları yoktur. Bunun yerine istemci, donanımın 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 kod modülasyonu (PCM) verilerini görebiliriz. Zaman damgaları, AAudio hizmeti tarafından düzenli olarak istenir ve ardından atomik mesaj kuyruğu aracılığıyla istemcinin zamanlama modeline iletilir.

PAYLAŞILMIŞ modda da bir zamanlama modeli kullanılır ancak bu model AAudioService'te bulunur.
Ses yakalama için benzer bir model kullanılır ancak PCM verileri ters yönde akar.
HAL değişiklikleri
tinyALSA için:
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:
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 ses HAL'i 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ğini bildirme
Ses çerçevesinin MMAP modunun ses HAL'i tarafından desteklendiğini bilmesi için "aaudio.mmap_policy" sistem özelliği 2 (AAUDIO_POLICY_AUTO) olarak ayarlanmalıdır. (Aşağıdaki "AAudio MMAP Veri Yolunu Etkinleştirme" bölümüne bakın.)
audio_policy_configuration.xml dosyası, MMAP istemcileri oluşturulduğunda Audio Policy Manager'ın hangi akışı açacağını bilmesi için MMAP/NO IRQ moduna özgü bir çıkış ve giriş profili de içermelidir:
<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>
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çılabilir ve kapatılabilir.
MMAP konumunu sorgulama
Zamanlama modeline geri iletilen zaman damgası, bir kare konumu ve nanosaniye cinsinden MONOTONIC zaman içerir:
getMmapPosition() generates (Result retval, MmapPosition position);
HAL, yeni bir Tinyalsa işlevi çağırarak bu bilgileri ALSA sürücüsünden edinebilir:
int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp);
Ortak bellek için dosya tanımlayıcıları
AAudio MMAP veri yolu, donanım ile ses hizmeti arasında paylaşılan bir bellek bölgesi kullanır. Paylaşılan belleğe, ALSA sürücüsü tarafından oluşturulan bir dosya tanımlayıcısı kullanılarak referans verilir.
Çekirdek değişiklikleri
Dosya tanımlayıcısı doğrudan bir /dev/snd/
sürücü dosyasıyla ilişkilendirilmişse AAudio hizmeti tarafından PAYLAŞILI modda kullanılabilir. Ancak tanımlayıcı, EXCLUSIVE modu için istemci koduna iletilemez. /dev/snd/
dosya tanımlayıcısı istemciye çok geniş erişim izni vereceğinden SELinux tarafından engellenir.
EXCLUSIVE modunu desteklemek için /dev/snd/
tanımlayıcısının anon_inode:dmabuf
dosya tanımlayıcısı olarak dönüştürülmesi gerekir. SELinux, bu dosya tanımlayıcısının istemciye iletilmesine izin verir. AAudioService tarafından da kullanılabilir.
Android Ion bellek kitaplığı kullanılarak anon_inode:dmabuf
dosya tanımlayıcısı oluşturulabilir.
Daha fazla bilgi için aşağıdaki harici kaynaklara bakın:
- "Android ION bellek ayırıcısı" https://lwn.net/Articles/480055/
- "Android ION'a genel bakış" https://wiki.linaro.org/BenjaminGaignard/ion
- "ION bellek ayırıcıyı entegre etme" https://lwn.net/Articles/565469/
HAL değişiklikleri
AAudio hizmetinin, bu anon_inode:dmabuf
özelliğinin desteklenip desteklenmediğini bilmesi gerekir. Android 10.0'dan önce bunu yapmanın tek yolu, MMAP arabelleğinin boyutunu negatif bir sayı olarak iletmektir (ör. Destekleniyorsa 2048 yerine -2048. Android 10.0 ve sonraki sürümlerde AUDIO_MMAP_APPLICATION_SHAREABLE
işaretini ayarlayabilirsiniz.
mmapBufferInfo |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Ses alt sistemi değişiklikleri
AAudio, orijinal AudioFlinger yoluna paralel çalışabilmesi için ses alt sisteminin ses ön ucunda ek bir veri yolu gerektirir. Bu eski yol, diğer tüm sistem sesleri ve uygulama sesleri için kullanılır. Bu işlev, DSP'deki bir yazılım karıştırıcı veya SOC'deki bir donanım karıştırıcı tarafından sağlanabilir.
AAudio MMAP veri yolunu etkinleştirme
MMAP desteklenmiyorsa veya bir akış açamazsa AAudio eski AudioFlinger veri yolunu kullanır. Bu nedenle AAudio, MMAP/NOIRQ yolunu desteklemeyen bir ses cihazıyla çalışır.
AAudio için MMAP desteğini test ederken aslında MMAP veri yolunu mu yoksa yalnızca eski veri yolunu mu test ettiğinizi bilmeniz önemlidir. Aşağıda, belirli veri yollarının nasıl etkinleştirileceği veya zorunlu kılınacağı ve bir akış tarafından kullanılan yolun nasıl sorgulandığı açıklanmaktadır.
Sistem özellikleri
MMAP politikasını sistem özellikleri aracılığıyla ayarlayabilirsiniz:
- 1 = AAUDIO_POLICY_NEVER: Yalnızca eski yolu kullanın. MMAP kullanmayı denemeyin.
- 2 = AAUDIO_POLICY_AUTO: MMAP'yi kullanmayı deneyin. Bu yöntem başarısız olursa veya kullanılamıyorsa eski yolu kullanın.
- 3 = AAUDIO_POLICY_ALWAYS: Yalnızca MMAP yolunu kullanın. Eski yola geri dönmeyin.
Bunlar, cihazlar Makefile'inde aşağıdaki gibi 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
Bu değerleri cihaz açıldıktan sonra da geçersiz kılabilirsiniz. Değişikliğin geçerli olması için ses sunucusunu yeniden başlatmanız gerekir. Örneğin, MMAP için AUTO modunu etkinleştirmek üzere:
adb root
adb shell setprop aaudio.mmap_policy 2
adb shell killall audioserver
ndk/sysroot/usr/include/aaudio/AAudioTesting.h
'te, MMAP yolunu kullanma politikasını geçersiz kılmanıza olanak tanıyan işlevler sağlanır:
aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy);
Bir akışta MMAP yolunun kullanılıp kullanılmadığını öğrenmek için şu işlevi çağırın:
bool AAudioStream_isMMapUsed(AAudioStream* stream);