AAudio ist eine Audio-API, die in der Android-Version 8.0 eingeführt wurde. Mit Android 8.1 Version verfügt über Verbesserungen zur Verringerung der Latenz, wenn sie in Verbindung mit einem HAL verwendet wird. und Treiber, die MMAP unterstützen. In diesem Dokument wird die Hardwareabstraktion beschrieben, Layer (HAL) und Treiberänderungen, die zur Unterstützung der MMAP-Funktion von AAudio in Android
Für die Unterstützung von AAudio MMAP ist Folgendes erforderlich:
- Meldung der MMAP-Funktionen des HAL
- Implementierung neuer Funktionen im HAL
- optional ein benutzerdefiniertes ioctl() für den Zwischenspeicher EXCLUSIVE-Modus implementieren
- einen zusätzlichen Hardware-Datenpfad angeben,
- Systemeigenschaften festlegen, die die MMAP-Funktion aktivieren
AAudio-Architektur
AAudio ist eine neue native C API, die eine Alternative zu Open SL ES bietet. Dabei wird ein Builder-Designmuster zum Erstellen von Audiostreams.
AAudio bietet einen Datenpfad mit niedriger Latenz. Im Modus EXKLUSIV ändert sich die Funktion ermöglicht es Clientanwendungscode, direkt in einen dem Arbeitsspeicher zugeordneten Zwischenspeicher zu schreiben das mit dem ALSA-Treiber geteilt wird. Im Modus SHARED wird der MMAP-Zwischenspeicher von ein Mischpult auf dem AudioServer. Im Modus EXCLUSIVE beträgt die Latenz deutlich geringer, da die Daten den Mixer umgehen.
Im Modus EXCLUSIVE fordert der Dienst den MMAP-Zwischenspeicher vom HAL an und verwaltet Ressourcen zu finden. Der MMAP-Zwischenspeicher wird im NOIRQ-Modus ausgeführt, sodass keine gemeinsam genutzten Lese-/Schreibzähler verwenden, um den Zugriff auf den Zwischenspeicher zu verwalten. Stattdessen muss die Kundin oder der Kunde ein Timing-Modell der Hardware unterhält und prognostiziert, wann der Puffer gelesen werden.
Im folgenden Diagramm sehen wir, wie die Pulscodemodulation (PCM)-Daten fließen über das MMAP FIFO in den ALSA-Treiber. Zeitstempel werden regelmäßig vom AAudio-Dienst angefordert und dann an das Timing-Modell des Clients übergeben. in einer atomaren Nachrichtenwarteschlange.
<ph type="x-smartling-placeholder">Im Modus SHARED wird auch ein Timing-Modell verwendet, das sich jedoch im AAudioService befindet.
Für die Audioerfassung wird ein ähnliches Modell verwendet, aber die PCM-Daten fließen in die entgegengesetzte Richtung an.
HAL-Änderungen
Informationen zu tinyALSA:
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);
Informationen zum alten 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);
Für 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);
MMAP-Unterstützung melden
Systemeigenschaft „aaudio.mmap_policy“ muss auf 2 festgelegt sein (AAUDIO_POLICY_AUTO), damit Das Audio-Framework erkennt, dass der MMAP-Modus vom Audio-HAL unterstützt wird. (siehe „AAudio-MMAP-Datenpfad aktivieren“ unten.)
Die Datei audio_policy_configuration.xml muss außerdem eine Ausgabe und eine Eingabe enthalten. speziell für den MMAP/NO IRQ-Modus konfiguriert, damit der Audio Policy Manager weiß, Welcher Stream geöffnet werden soll, wenn MMAP-Clients erstellt werden:
<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-Stream öffnen und schließen
createMmapBuffer(int32_t minSizeFrames) generates (Result retval, MmapBufferInfo info);
Der MMAP-Stream kann durch Aufrufen von Tinyalsa-Funktionen geöffnet und geschlossen werden.
MMAP-Position abfragen
Der Zeitstempel, der an das Timing-Modell zurückgegeben wird, enthält eine Frame-Position und einen MONOTONISCHE Zeit in Nanosekunden:
getMmapPosition() generates (Result retval, MmapPosition position);
Der HAL kann diese Informationen aus dem ALSA-Treiber abrufen, indem er eine neue Tinyalsa-Funktion:
int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp);
Dateideskriptoren für gemeinsamen Arbeitsspeicher
Der AAudio-MMAP-Datenpfad verwendet einen Speicherbereich, der von den als auch den Audiodienst verwenden. Auf den freigegebenen Arbeitsspeicher wird mit einem Dateideskriptor verwiesen das vom ALSA-Treiber generiert wird.
Kernel-Änderungen
Ist der Dateideskriptor direkt mit einer
/dev/snd/
-Treiberdatei hoch, kann sie vom AAudio-Dienst in
SHARED. Der Deskriptor kann jedoch nicht an den Clientcode für
EXKLUSIV. Der Dateideskriptor /dev/snd/
würde ebenfalls
Zugriffsrechte für den Client haben, sodass er durch SELinux blockiert wird.
Zur Unterstützung des EXKLUSIV-Modus muss das Attribut
/dev/snd/
-Deskriptor für eine anon_inode:dmabuf
-Datei
Beschreibung. SELinux ermöglicht die Übergabe dieses Dateideskriptors an den Client. Es
kann auch vom AAudioService verwendet werden.
Ein anon_inode:dmabuf
-Dateideskriptor kann mithilfe der
Android-Ion-Speicherbibliothek.
Weitere Informationen finden Sie in diesen externen Ressourcen:
- „Android ION-Arbeitsspeicherzuweisung“ https://lwn.net/Articles/480055/
- „Übersicht zu Android ION“ https://wiki.linaro.org/BenjaminGaignard/ion
- „ION-Arbeitsspeicherzuweisung einbinden“ https://lwn.net/Articles/565469/.
HAL-Änderungen
Der AAudio-Dienst muss wissen, ob anon_inode:dmabuf
unterstützt. Vor Android 10.0 war dies nur möglich, wenn die Größe des MMAP übergeben wurde.
Puffer als negative Zahl, z. B. -2048 statt 2048, falls unterstützt. Android 10.0 und höher
können Sie das Flag AUDIO_MMAP_APPLICATION_SHAREABLE
festlegen.
mmapBufferInfo |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Änderungen im Audiosubsystem
Für AAudio ist ein zusätzlicher Datenpfad am Audio-Front-End erforderlich. Subsystem , damit es parallel zum ursprünglichen AudioFlinger-Pfad funktionieren kann. Dieser Legacy-Pfad wird für alle anderen System- und Anwendungstöne verwendet. Diese Funktion kann von einem Softwaremixer in einer DSP oder einer Hardware im Sicherheitscenter.
AAudio-MMAP-Datenpfad aktivieren
AAudio verwendet den alten AudioFlinger-Datenpfad, wenn MMAP nicht unterstützt wird oder wenn ein Stream nicht geöffnet wird. AAudio funktioniert also mit einem Audiogerät, das keine unterstützen den MMAP/NOIRQ-Pfad.
Beim Testen der MMAP-Unterstützung für AAudio ist es wichtig zu wissen, den MMAP-Datenpfad oder nur den Legacy-Datenpfad testen. Die Im Folgenden wird beschrieben, wie Sie bestimmte Datenpfade aktivieren oder erzwingen und wie Sie Abfragen Pfad eines Streams.
Systemeigenschaften
Sie können die MMAP-Richtlinie über die Systemeigenschaften festlegen:
- 1 = AAUDIO_POLICY_NEVER – nur Legacy-Pfad verwenden Versuchen Sie nicht einmal, MMAP zu verwenden.
- 2 = AAUDIO_POLICY_AUTO – Versuchen Sie, MMAP zu verwenden. Wenn dies fehlschlägt oder nicht verfügbar ist, und verwenden Sie dann den Legacy-Pfad.
- 3 = AAUDIO_POLICY_ALWAYS – Nur MMAP-Pfad verwenden Nicht auf Legacy-Version zurückgreifen Pfad.
Diese können im Geräte-Makefile festgelegt werden:
# 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
Sie können diese Werte auch überschreiben, nachdem das Gerät gestartet wurde. Du musst den Audioserver neu starten, damit die Änderung wirksam wird. So aktivieren Sie beispielsweise den Modus AUTO für MMAP:
adb root
adb shell setprop aaudio.mmap_policy 2
adb shell killall audioserver
Es gibt Funktionen in den
ndk/sysroot/usr/include/aaudio/AAudioTesting.h
, mit denen Sie Folgendes tun können:
die Richtlinie für die Verwendung des MMAP-Pfads überschreiben:
aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy);
Um herauszufinden, ob ein Stream den MMAP-Pfad verwendet, rufen Sie Folgendes auf:
bool AAudioStream_isMMapUsed(AAudioStream* stream);