Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

AAudio dan MMAP

AAudio adalah API audio yang diperkenalkan pada rilis Android 8.0. Rilis Android 8.1 memiliki penyempurnaan untuk mengurangi latensi saat digunakan bersama dengan HAL dan driver yang mendukung MMAP. Dokumen ini menjelaskan lapisan abstraksi perangkat keras (HAL) dan perubahan driver yang diperlukan untuk mendukung fitur MMAP AAudio di Android.

Dukungan untuk AAudio MMAP membutuhkan:

  • melaporkan kapabilitas MMAP dari HAL
  • mengimplementasikan fungsi baru di HAL
  • opsional mengimplementasikan ioctl khusus () untuk buffer mode EKSKLUSIF
  • menyediakan jalur data perangkat keras tambahan
  • mengatur properti sistem yang mengaktifkan fitur MMAP

Arsitektur AAudio

AAudio adalah C API asli baru yang menyediakan alternatif untuk Open SL ES. Ini menggunakan pola desain Builder untuk membuat aliran audio.

AAudio menyediakan jalur data latensi rendah. Dalam mode EKSKLUSIF, fitur ini memungkinkan kode aplikasi klien untuk menulis langsung ke buffer yang dipetakan memori yang dibagikan dengan driver ALSA. Dalam mode SHARED, buffer MMAP digunakan oleh mixer yang berjalan di AudioServer. Dalam mode EKSKLUSIF, latensi jauh lebih sedikit karena data melewati mixer.

Dalam mode EKSKLUSIF, layanan meminta buffer MMAP dari HAL dan mengelola sumber daya. Buffer MMAP berjalan dalam mode NOIRQ, jadi tidak ada penghitung baca / tulis bersama untuk mengelola akses ke buffer. Sebaliknya, klien mempertahankan model pengaturan waktu perangkat keras dan memprediksi kapan buffer akan dibaca.

Pada diagram di bawah ini, kita dapat melihat data Pulse-code modulation (PCM) mengalir melalui MMAP FIFO ke driver ALSA. Stempel waktu diminta secara berkala oleh layanan AAudio dan kemudian diteruskan ke model waktu klien melalui antrian pesan atom.

Diagram aliran data PCM.
Gambar 1. Aliran data PCM melalui FIFO ke ALSA

Dalam mode SHARED, model pengaturan waktu juga digunakan, tetapi berada di AAudioService.

Untuk perekaman audio, model serupa digunakan, tetapi data PCM mengalir ke arah yang berlawanan.

Perubahan HAL

Untuk tinyALSA lihat:

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);

Untuk HAL lawas, lihat:

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);

Untuk audio HIDL 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);

Melaporkan dukungan MMAP

Properti sistem "aaudio.mmap_policy" harus disetel ke 2 (AAUDIO_POLICY_AUTO) sehingga framework audio mengetahui bahwa mode MMAP didukung oleh audio HAL. (lihat "Mengaktifkan Jalur Data MMAP AAudio" di bawah.)

File audio_policy_configuration.xml juga harus berisi output dan profil input khusus untuk mode MMAP / NO IRQ sehingga Manajer Kebijakan Audio mengetahui aliran mana yang akan dibuka ketika klien MMAP dibuat:

<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>

Membuka dan menutup aliran MMAP

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

Aliran MMAP dapat dibuka dan ditutup dengan memanggil fungsi Tinyalsa.

Menanyakan posisi MMAP

Stempel waktu yang diteruskan kembali ke Model Waktu berisi posisi bingkai dan waktu MONOTONIC dalam nanodetik:

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

HAL dapat memperoleh informasi ini dari driver ALSA dengan memanggil fungsi Tinyalsa baru:

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

Perubahan kernel

Aktifkan mode MMAP / NOIRQ di driver.

Memori bersama direferensikan menggunakan deskriptor file yang dihasilkan oleh driver ALSA. Jika deskriptor file secara langsung dikaitkan dengan file /dev/snd/ driver, maka itu dapat digunakan oleh layanan AAudio dalam mode SHARED. Tetapi deskriptor tidak dapat diteruskan ke kode klien untuk mode EKSKLUSIF. Deskriptor /dev/snd/ file akan memberikan akses yang terlalu luas ke klien, sehingga diblokir oleh SELinux.

Untuk mendukung mode EKSKLUSIF, Anda perlu mengonversi /dev/snd/ deskriptor ke deskriptor file anon_inode:dmabuf . SELinux memungkinkan deskriptor file itu diteruskan ke klien. Ini juga dapat digunakan oleh AAudioService.

anon_inode:dmabuf file anon_inode:dmabuf dapat dibuat menggunakan pustaka memori Android Ion.

Untuk informasi tambahan, lihat sumber daya eksternal ini:

  1. "Pengalokasi memori Android ION" https://lwn.net/Articles/480055/
  2. "Ikhtisar Android ION" https://wiki.linaro.org/BenjaminGaignard/ion
  3. "Mengintegrasikan pengalokasi memori ION" https://lwn.net/Articles/565469/

Layanan AAudio perlu mengetahui apakah anon_inode:dmabuf ini didukung. Saat ini, satu-satunya cara untuk melakukannya adalah dengan melewatkan ukuran buffer MMAP sebagai angka negatif, misalnya. -2048, bukan 2048, jika didukung. Cara yang lebih baik untuk melaporkan ini tanpa harus membuka aliran telah direncanakan.

Perubahan subsistem audio

AAudio memerlukan jalur data tambahan di ujung depan audio subsistem audio sehingga dapat beroperasi secara paralel dengan jalur AudioFlinger asli. Jalur warisan itu digunakan untuk semua suara sistem dan suara aplikasi lainnya. Fungsionalitas ini dapat disediakan oleh mixer perangkat lunak di DSP atau mixer perangkat keras di SOC.

Mengaktifkan Jalur Data AAudio MMAP

AAudio akan menggunakan jalur data AudioFlinger lama jika MMAP tidak didukung atau gagal membuka aliran. Jadi AAudio akan bekerja dengan perangkat audio yang tidak mendukung jalur MMAP / NOIRQ.

Saat menguji dukungan MMAP untuk AAudio, penting untuk mengetahui apakah Anda benar-benar menguji jalur data MMAP atau hanya menguji jalur data lama. Berikut ini menjelaskan cara mengaktifkan atau memaksa jalur data tertentu, dan cara menanyakan jalur yang digunakan oleh aliran.

Properti sistem

Anda dapat mengatur kebijakan MMAP melalui properti sistem:

  • 1 = AAUDIO_POLICY_NEVER - Hanya gunakan jalur lama. Jangan coba-coba menggunakan MMAP.
  • 2 = AAUDIO_POLICY_AUTO - Coba gunakan MMAP. Jika gagal atau tidak tersedia, gunakan jalur lama.
  • 3 = AAUDIO_POLICY_ALWAYS - Hanya gunakan jalur MMAP. Jangan kembali ke jalur lama.

Ini dapat diatur di perangkat Makefile, seperti:

# 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

Anda juga dapat mengganti nilai ini setelah perangkat di-boot. Anda perlu memulai ulang server audio agar perubahan diterapkan. Misalnya, untuk mengaktifkan mode AUTO untuk MMAP:

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

Ada fungsi yang disediakan di ndk/sysroot/usr/include/aaudio/AAudioTesting.h yang memungkinkan Anda mengganti kebijakan untuk menggunakan jalur MMAP:

aaudio_result_t AAudio_setMMapPolicy(aaudio_policy_t policy);

Untuk mengetahui apakah aliran menggunakan jalur MMAP, hubungi:

bool AAudioStream_isMMapUsed(AAudioStream* stream);