AAudio und MMAP

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">
</ph> PCM-Datenflussdiagramm.
Abbildung 1: PCM-Datenfluss durch FIFO zu ALSA

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:

  1. „Android ION-Arbeitsspeicherzuweisung“ https://lwn.net/Articles/480055/
  2. „Übersicht zu Android ION“ https://wiki.linaro.org/BenjaminGaignard/ion
  3. „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 am 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);