AAudio to interfejs API audio wprowadzony w Androidzie 8.0. Android 8.1 wersja zawiera ulepszenia, które zmniejszają opóźnienie, gdy jest używana w połączeniu z HAL i sterownik obsługujący standard MMAP. Ten dokument opisuje abstrakcję sprzętu warstwa (HAL) i sterowniki wymagane do obsługi funkcji MMAP AAudio. na urządzeniu z Androidem.
Obsługa AAudio MMAP wymaga:
- raportowania możliwości MMAP dla HAL.
- wdrażanie nowych funkcji w HAL.
- opcjonalnie wdrożenie niestandardowej funkcji ioctl() dla bufora trybu WYKLUCZAJĄCEGO
- udostępniając dodatkową ścieżkę danych dotyczących sprzętu
- Ustawianie właściwości systemu, które włączają funkcję MMAP
Architektura AAudio
AAudio to nowy, natywny interfejs API C, który stanowi alternatywę dla Open SL ES. Wykorzystuje Wzór projektu konstruktora do tworzenia strumieni audio.
AAudio zapewnia ścieżkę danych z małym opóźnieniem. W trybie WYJĄTKOWYM funkcja umożliwia kodowi aplikacji klienckiej zapisywanie bezpośrednio w buforze zmapowanym pamięci które jest udostępniane sterownikowi ALSA. W trybie SHARED bufor MMAP jest używany przez z mikserem na serwerze audio. W trybie WYJĄTKOWY opóźnienie jest znacznie mniej, ponieważ dane omijają mikser.
W trybie WYJĄTKOWYM usługa żąda bufora MMAP z HAL i zarządza dostęp do zasobów. Bufor MMAP działa w trybie NOIRQ, dlatego nie ma żadnych udostępnionych liczników odczytu/zapisu w celu zarządzania dostępem do bufora. Zamiast tego, Utrzymuje model czasowy sprzętu i prognozuje, kiedy bufor zostanie przeczytaj.
Na poniższym diagramie widać przepływ danych modulacji kodu PCM (Pulse-code modulation, PCM) przez urządzenie MMAP FIFO do sterownika ALSA. Sygnatury czasowe są podawane okresowo żądane przez usługę AAudio, a następnie przekazane do modelu czasowego klienta dzięki niepodzielnej kolejki komunikatów.
.W trybie SHARED używany jest również model czasowy, ale działa on w usłudze AAudioService.
Do przechwytywania dźwięku stosowany jest podobny model, ale przepływ danych PCM w przeciwnym kierunku.
Zmiany HAL
W przypadku tinyALSA zobacz:
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);
Informacje o starszej wersji HAL:
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);
W przypadku HIDL Audio HAL:
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);
Zgłaszanie obsługi MMAP
Właściwość systemowa „aaudio.mmap_policy” powinna mieć wartość 2 (AAUDIO_POLICY_AUTO), więc platforma audio wie, że tryb MMAP jest obsługiwany przez HAL audio. (zobacz „Włączanie ścieżki danych MMAP” Audio below.)
Plik audio_policy_configuration.xml musi też zawierać dane wyjściowe i dane wejściowe profilu w trybie MMAP/NO IRQ. Dzięki temu menedżer zasad dotyczących dźwięku wie, który strumień ma otwierać się podczas tworzenia klientów MMAP:
<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>
Otwieranie i zamykanie strumienia MMAP
createMmapBuffer(int32_t minSizeFrames) generates (Result retval, MmapBufferInfo info);
Strumień MMAP można otwierać i zamykać za pomocą funkcji Tinyalsa.
Pozycja MMAP zapytania
Sygnatura czasowa przekazana z powrotem do modelu czasu zawiera pozycję klatki i tag Czas MONOTONICS w nanosekundach:
getMmapPosition() generates (Result retval, MmapPosition position);
HAL może uzyskać te informacje od kierowcy ALSA, dzwoniąc pod nowy Funkcja Tinyalsa:
int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp);
Deskryptory plików dla pamięci współdzielonej
Ścieżka danych AAudio MMAP korzysta z regionu pamięci współużytkowanego przez sprzęt i usługę audio. Odwołanie do pamięci współdzielonej odbywa się za pomocą deskryptora pliku generowane przez sterownik ALSA.
Zmiany jądra systemu
Jeśli deskryptor pliku jest bezpośrednio powiązany z
/dev/snd/
, może być używany przez usługę AAudio
Tryb UDOSTĘPNIONE. Nie można jednak przekazać deskryptora do kodu klienta dla
Tryb WYJĄTKOWY. Deskryptor pliku /dev/snd/
również dostarczyłby
do szerokiego dostępu do klienta, dlatego blokuje go SELinux.
Do obsługi trybu WYJĄTKOWEGO trzeba przekonwertować parametr
Deskryptor /dev/snd/
do pliku anon_inode:dmabuf
deskryptor. SELinux zezwala na przekazanie deskryptora pliku do klienta. it
może być również używany przez usługę AAudioService.
Deskryptor pliku anon_inode:dmabuf
można wygenerować za pomocą
Biblioteka pamięci Android Ion.
Więcej informacji znajdziesz w tych materiałach zewnętrznych:
- „Funkcja przydzielania pamięci Androida ION” https://lwn.net/Articles/480055/
- „Android ION przegląd” https://wiki.linaro.org/BenjaminGaignard/ion
- „Integrowanie pamięci przydzielającej ION” https://lwn.net/Articles/565469/
Zmiany HAL
Usługa AAudio musi wiedzieć, czy to anon_inode:dmabuf
obsługiwane. Przed Androidem 10.0 jedynym sposobem na to było przesłanie pliku MMAP
buforuj jako liczbę ujemną, np. -2048 zamiast 2048, jeśli jest obsługiwana. Na Androidzie 10.0 i nowszych
możesz ustawić flagę AUDIO_MMAP_APPLICATION_SHAREABLE
.
mmapBufferInfo |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Zmiany podsystemu audio
AAudio wymaga dodatkowej ścieżki danych po stronie interfejsu audio więc może on działać równolegle z pierwotną ścieżką dźwiękową AudioFlinger. Ta starsza ścieżka będzie używana w przypadku wszystkich pozostałych dźwięków systemowych i dźwięków aplikacji. Funkcję tę może zapewnić mikser oprogramowania na platformie DSP lub sprzęt mikser w SOC.
Włącz ścieżkę danych AAudio MMAP
AAudio będzie używać starszej ścieżki danych AudioFlinger, jeśli format MMAP nie będzie obsługiwany lub nie udało się otworzyć strumienia. Dlatego AAudio będzie działać z urządzeniem audio, które nie obsługi ścieżki MMAP/NOIRQ.
Podczas testowania obsługi MMAP w AAudio trzeba sprawdzić, czy testowanie ścieżki danych MMAP lub tylko testowanie starszej ścieżki danych. Z tego artykułu dowiesz się, jak włączyć lub wymusić określone ścieżki danych oraz jak tworzyć zapytania ścieżkę używaną przez strumień.
Właściwości systemowe
Zasadę MMAP możesz ustawić za pomocą właściwości systemowych:
- 1 = AAUDIO_POLICY_NEVER – używaj tylko starszej ścieżki. Nie próbuj nawet używać MMAP.
- 2 = AAUDIO_POLICY_AUTO – staraj się używać MMAP. Jeśli to się nie uda lub będzie niedostępne, użyj starszej ścieżki.
- 3 = AAUDIO_POLICY_ALWAYS – używaj tylko ścieżki MMAP. Nie powracaj do starszej wersji ścieżki konwersji.
Możesz je ustawić w pliku Makefile na urządzeniu:
# 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
Możesz też zastąpić te wartości po uruchomieniu urządzenia. Aby zmiana zaczęła obowiązywać, musisz ponownie uruchomić serwer audio. Aby na przykład włączyć tryb AUTO w przypadku MMAP:
adb root
adb shell setprop aaudio.mmap_policy 2
adb shell killall audioserver
Funkcje dostępne w
ndk/sysroot/usr/include/aaudio/AAudioTesting.h
, dzięki którym możesz:
zastąp zasadę dotyczącą korzystania ze ścieżki MMAP:
aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy);
Aby sprawdzić, czy strumień korzysta ze ścieżki MMAP, wywołaj:
bool AAudioStream_isMMapUsed(AAudioStream* stream);