Konfigurowanie zasad dotyczących audio

W wersji Androida 10 wprowadzono znaczącą refaktoryzację menedżera zasad dotyczących dźwięku, aby zapewnić większą elastyczność w obsłudze złożonych zastosowań samochodowych:

  • Strategie routingu właściwe dla OEM.
  • Grupy głośności, które można dostosowywać, dla grup starszych typów strumieni za pomocą tych samych krzywych głośności.
  • strategie routingu deklarowane przez mechanizm zasad audio zamiast być zakodowane na stałe.
  • Krzywe głośności i grupy zarządzane przez silnik zasad dotyczących dźwięku.
  • Wewnętrzne refaktoryzowanie przygotowujące do przyszłego podziału na kod wspólny i konfigurowalny oraz oferujący zaawansowane funkcje zarządzania urządzeniami audio. Na przykład w regułach zasad można używać wszystkich właściwości urządzenia, a nie tylko jego typu.

W Androidzie 7.0 wprowadzono format pliku konfiguracji zasad audio (XML) do opisywania topologii audio.

Poprzednie wersje Androida wymagały użycia device/<company>/<device>/audio/audio_policy.conf do zadeklarowania urządzeń audio dostępnych w produkcie (przykład tego pliku dotyczy sprzętu audio Galaxy Nexus w device/samsung/tuna/audio/audio_policy.conf). CONF to prosty, zastrzeżony format, którego nie można opisać zbyt złożonym topologią dla branż takich jak telewizory czy samochody.

wycofano obsługę Androida 7.0 audio_policy.conf i dodano obsługę definiowania topologii audio za pomocą formatu pliku XML, który jest bardziej czytelny dla człowieka, zawiera szeroki zakres narzędzi do edycji i analizy oraz jest na tyle elastyczny, że umożliwia opisywanie złożonych topologii audio. Android 7.0 używa flagi kompilacji USE_XML_AUDIO_POLICY_CONF do wyboru formatu XML plików konfiguracji.

Zalety formatu XML

Podobnie jak w przypadku pliku CONF, plik XML pozwala określić liczbę i typy profili strumieni wyjściowych, urządzeń używanych do odtwarzania i przechwytywania oraz atrybuty audio. Format XML zapewnia też te ulepszenia:

  • W Androidzie 10 można jednocześnie używać więcej niż 1 aktywnej aplikacji do nagrywania.
    • Rozpoczęcie nagrywania nigdy nie jest odrzucane z powodu sytuacji równoległej.
    • Funkcja registerAudioRecordingCallback(AudioManager.AudioRecordingCallback cb) powiadamia klientów o zmianach ścieżki przechwytywania.
  • W tych sytuacjach klient otrzymuje cichsze próbki dźwiękowe:
    • Aktywny jest przypadek użycia, który wymaga ochrony prywatności (np. VOICE_COMMUNICATION).
    • Klient nie ma usługi na pierwszym planie ani interfejsu użytkownika na pierwszym planie.
    • Role specjalne są rozpoznawane przez zasady:
      • Usługa ułatwień dostępu: może nagrywać nawet wtedy, gdy aktywne jest zastosowanie wymagające ochrony prywatności.
      • Asystent: uznawany za poważną ochronę prywatności, jeśli interfejs jest umieszczony na samej górze.
  • Profile audio mają strukturę podobną do prostych deskryptorów audio HDMI, co umożliwia stosowanie różnych zestawów częstotliwości próbkowania i masek kanałów w przypadku każdego formatu audio.
  • Istnieją konkretne definicje wszystkich możliwych połączeń między urządzeniami i strumieniami. Wcześniej reguła domyślna umożliwiała połączenie wszystkich urządzeń podłączonych do tego samego modułu HAL, uniemożliwiając zasadom dotyczącym dźwięku kontrolowanie połączeń żądanych za pomocą interfejsów API łatki audio. W formacie XML opis topologii definiuje ograniczenia połączeń.
  • Obsługa includes pozwala uniknąć powtarzania standardowych definicji A2DP, USB lub reroute submit.
  • Krzywe głośności można dostosowywać. Wcześniej tabele woluminów były zakodowane na stałe. W formacie XML tabele objętości są opisane i można je dostosować.

Szablon dostępny pod adresemframeworks/av/services/audiopolicy/config/audio_policy_configuration.xmlpokazuje wiele z tych funkcji w akcji.

Format i lokalizacja pliku

Nowy plik konfiguracji zasad audio to audio_policy_configuration.xml i znajduje się w lokalizacji /system/etc. Poniższe przykłady przedstawiają prostą konfigurację zasad audio w formacie pliku XML dla Androida 12 i wersji Androida 12 starszych.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
    <globalConfiguration speaker_drc_enabled="true"/>
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>Speaker</item>
                <item>Earpiece</item>
                <item>Built-In Mic</item>
            </attachedDevices>
            <defaultOutputDevice>Speaker</defaultOutputDevice>
            <mixPorts>
                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
                <mixPort name="primary input" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="8000 16000 48000"
                             channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </devicePort>
                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </devicePort>
                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </devicePort>
                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="8000 16000 48000"
                             channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </devicePort>
                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="8000 16000 48000"
                             channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="Earpiece" sources="primary output"/>
                <route type="mix" sink="Speaker" sources="primary output"/>
                <route type="mix" sink="Wired Headset" sources="primary output"/>
                <route type="mix" sink="primary input" sources="Built-In Mic,Wired Headset Mic"/>
            </routes>
        </module>
        <xi:include href="a2dp_audio_policy_configuration.xml"/>
    </modules>

    <xi:include href="audio_policy_volumes.xml"/>
    <xi:include href="default_volume_tables.xml"/>
</audioPolicyConfiguration>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
    <globalConfiguration speaker_drc_enabled="true"/>
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>Speaker</item>
                <item>Earpiece</item>
                <item>Built-In Mic</item>
            </attachedDevices>
            <defaultOutputDevice>Speaker</defaultOutputDevice>
            <mixPorts>
                <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
                <mixPort name="primary input" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="8000,16000,48000"
                             channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink">
                   <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </devicePort>
                <devicePort tagName="Speaker" role="sink" type="AUDIO_DEVICE_OUT_SPEAKER" address="">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </devicePort>
                <devicePort tagName="Wired Headset" type="AUDIO_DEVICE_OUT_WIRED_HEADSET" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </devicePort>
                <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="8000,16000,48000"
                             channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </devicePort>
                <devicePort tagName="Wired Headset Mic" type="AUDIO_DEVICE_IN_WIRED_HEADSET" role="source">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                             samplingRates="8000,16000,48000"
                             channelMasks="AUDIO_CHANNEL_IN_MONO"/>
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="Earpiece" sources="primary output"/>
                <route type="mix" sink="Speaker" sources="primary output"/>
                <route type="mix" sink="Wired Headset" sources="primary output"/>
                <route type="mix" sink="primary input" sources="Built-In Mic,Wired Headset Mic"/>
            </routes>
        </module>
        <xi:include href="a2dp_audio_policy_configuration.xml"/>
    </modules>

    <xi:include href="audio_policy_volumes.xml"/>
    <xi:include href="default_volume_tables.xml"/>
</audioPolicyConfiguration>

Struktura najwyższego poziomu zawiera moduły odpowiadające poszczególnym modułom sprzętowym HAL audio. Każdy moduł ma listę portów miksowania, portów urządzenia i tras:

  • Porty miksowania opisują możliwe profile konfiguracji strumieni, które można otworzyć w HAL dźwięku na potrzeby odtwarzania i przechwytywania.
  • Porty urządzeń opisują urządzenia, które można podłączyć za pomocą ich typu (i opcjonalnie adres i właściwości audio, jeśli są potrzebne).
  • Trasy są oddzielone od deskryptora portów, co umożliwia opis tras między urządzeniami lub przesyłanie strumieniowe na urządzenie.

Tabele głośności to proste listy punktów definiujących krzywą używaną do przekształcania indeksu interfejsu w głośność w dB. Oddzielny plik include zawiera domyślne krzywe, ale każdą krzywą dla danego zastosowania i kategorii urządzenia można zastąpić.

<?xml version="1.0" encoding="UTF-8"?>
<volumes>
    <reference name="FULL_SCALE_VOLUME_CURVE">
        <point>0,0</point>
        <point>100,0</point>
    </reference>
    <reference name="SILENT_VOLUME_CURVE">
        <point>0,-9600</point>
        <point>100,-9600</point>
    </reference>
    <reference name="DEFAULT_VOLUME_CURVE">
        <point>1,-4950</point>
        <point>33,-3350</point>
        <point>66,-1700</point>
        <point>100,0</point>
    </reference>
</volumes>
<?xml version="1.0" encoding="UTF-8"?>
<volumes>
    <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_VOICE_CALL" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_SYSTEM" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_RING" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA"ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
        <point>1,-5500</point>
        <point>20,-4300</point>
        <point>86,-1200</point>
        <point>100,0</point>
    </volume>
    <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ALARM" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_NOTIFICATION" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_BLUETOOTH_SCO" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ENFORCED_AUDIBLE" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_DTMF" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="SILENT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="SILENT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_TTS" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="SILENT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="DEFAULT_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_ACCESSIBILITY" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="DEFAULT_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_REROUTING" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>

    <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_HEADSET" ref="FULL_SCALE_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_SPEAKER" ref="FULL_SCALE_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_EARPIECE" ref="FULL_SCALE_VOLUME_CURVE"/>
    <volume stream="AUDIO_STREAM_PATCH" deviceCategory="DEVICE_CATEGORY_EXT_MEDIA" ref="FULL_SCALE_VOLUME_CURVE"/>
</volumes>

Uwzględnianie plików

Metody uwzględniania XML (XInclude) można używać do uwzględniania informacji o konfiguracji zasad dotyczących dźwięku znajdujących się w innych plikach XML. Wszystkie uwzględnione pliki muszą mieć strukturę opisaną powyżej z tymi ograniczeniami:

  • Pliki mogą zawierać tylko elementy najwyższego poziomu.
  • Pliki nie mogą zawierać elementów XInclude.

Używaj go, aby uniknąć kopiowania informacji o standardowych konfiguracjach modułu HAL dźwięku z projektu Android Open Source (AOSP) do wszystkich plików konfiguracji zasad dźwięku (co może powodować błędy). Standardowy plik XML konfiguracji zasad audio jest dostępny dla tych interfejsów HAL dźwięku:

  • A2DP: a2dp_audio_policy_configuration.xml
  • Przekieruj submiksję: rsubmix_audio_policy_configuration.xml
  • USB: usb_audio_policy_configuration.xml

Organizacja kodu zasad dotyczących dźwięku

AudioPolicyManager.cpp jest podzielony na kilka modułów, aby ułatwić jego utrzymanie i konfigurowanie. Organizacja frameworks/av/services/audiopolicy zawiera te moduły:

Moduł Opis
/managerdefault Zawiera ogólne interfejsy i implementację działania typowe dla wszystkich aplikacji. Podobnie jak w przypadku AudioPolicyManager.cpp, funkcje silnika i pojęcia ogólne są abstrakcyjne.
/common Definiuje klasy podstawowe (np. struktury danych dla profili wejściowych profili strumienia audio, deskryptorów urządzeń audio, poprawek audio i portów audio). Wcześniej była ona zdefiniowana w AudioPolicyManager.cpp.
/engine

implementuje reguły określające, których urządzeń i głośników należy używać w danym przypadku użycia. Implementuje standardowy interfejs z częścią ogólną, na przykład aby uzyskać odpowiednie urządzenie do danego przypadku użycia odtwarzania lub rejestrowania, albo aby ustawić połączone urządzenia lub stan zewnętrzny (czyli stan wywołania w przypadku wymuszonego użycia), który może zmienić decyzję dotyczącą routingu.

Dostępne w 2 wersjach: konfigurowalnejdomyślnej. Informacje o wyborze wersji znajdziesz w artykule na temat konfigurowania za pomocą platformy parametrów.

/engineconfigurable Implementacja mechanizmu zasad, która opiera się na ramach parametrów (patrz poniżej). Konfiguracja opiera się na ramach parametrów i zasadach zdefiniowanych w plikach XML.
/enginedefault Implementacja Policy Engine na podstawie poprzednich implementacji Menedżera zasad dotyczących dźwięku na urządzeniach z Androidem. Jest to domyślna opcja, która zawiera zakodowane na stałe reguły odpowiadające implementacjom w Nexusie i AOSP.
/service Obejmuje interfejsy bindera, implementację wątków i blokowania z interfejsem do reszty frameworka.

Konfiguracja za pomocą ramki parametrów

Kod zasad dotyczących dźwięku jest uporządkowany w sposób ułatwiający jego zrozumienie i utrzymanie, a jednocześnie obsługuje zasady dźwięku zdefiniowane wyłącznie przez pliki konfiguracji. Organizacja i projekt zasad dotyczących dźwięku są oparte na platformie Intel Parameter Framework, która jest platformą opartą na wtyczkach i regułach do obsługi parametrów.

Dzięki konfigurowalnej polityce dotyczącej dźwięku producenci OEM mogą:

  • Opisz strukturę systemu i jego parametry w formacie XML.
  • Aby uzyskać dostęp do opisanych parametrów, napisz (w C++) lub ponownie użyj backendu (wtyczki).
  • Zdefiniuj (w XML-u lub w języku domeny) warunki lub reguły, według których dany parametr musi przyjmować określoną wartość.

AOSP zawiera przykładowy plik konfiguracji zasad audio, który korzysta z ramy parametrycznej (Frameworks/av/services/audiopolicy/engineconfigurable/parameter-framework/example/Settings/PolicyConfigurableDomains.xml). Szczegółowe informacje znajdziesz w dokumentacji firmy Intel na temat ramy danych.

W Androidzie 10 i starszych wersjach zasada dotycząca dźwięku z możliwością konfigurowania jest wybierana za pomocą opcji kompilacji USE_CONFIGURABLE_AUDIO_POLICY. W Androidzie 11 lub nowszym wersja silnika zasad dotyczących dźwięku jest wybierana w pliku audio_policy_configuration.xml. Aby wybrać konfigurowalny mechanizm zasad dotyczących dźwięku, ustaw wartość atrybutu engine_library elementu globalConfiguration na configurable, jak w tym przykładzie:

<audioPolicyConfiguration>
    <globalConfiguration engine_library="configurable" />
...
</audioPolicyConfiguration>

Interfejsy API routingu zasad audio

Android 6.0 wprowadził publiczny interfejs API Enumeration and Selection, który działa na podstawie infrastruktury łatki audio lub portu audio i umożliwia deweloperom aplikacji wskazanie preferowanego wyjścia lub wejścia na urządzeniu dla połączonych nagrań lub ścieżek audio.

W Androidzie 7.0 interfejs API do zliczania i wyboru jest weryfikowany przez testy CTS oraz rozszerzony o przekierowywanie natywnych strumieni audio C/C++ (OpenSL ES). Przekierowywanie strumieni natywnych nadal odbywa się w języku Java, ale z dodatkiem interfejsu AudioRouting, który zastępuje, łączy i wycofa jawne metody kierowania, które były specyficzne dla klas AudioTrackAudioRecord.

Szczegółowe informacje o interfejsie Enumeration and Selection API znajdziesz w artykułach na temat interfejsów konfiguracji Androida oraz OpenSLES_AndroidConfiguration.h. Szczegółowe informacje o przesyłaniu dźwięku znajdziesz w artykule AudioRouting.

Pomoc dostępna w wielu kanałach

Jeśli sprzęt i sterownik obsługują dźwięk wielokanałowy przez HDMI, możesz przesyłać strumień audio bezpośrednio do sprzętu audio (omijając mikser AudioFlinger, dzięki czemu nie zostanie on zmiksowany do 2 kanałów). HAL dźwięku musi udostępniać informacje o tym, czy profil strumienia wyjściowego obsługuje funkcje dźwięku wielokanałowego. Jeśli HAL ujawnia swoje możliwości, domyślny menedżer zasad zezwala na odtwarzanie wielokanałowe przez HDMI. Szczegóły wdrażania znajdziesz w dokumentacji device/samsung/tuna/audio/audio_hw.c.

Aby określić, że Twój produkt zawiera wyjście audio wielokanałowe, zmodyfikuj plik konfiguracji zasad dotyczących dźwięku, aby opisać wyjście wielokanałowe dla produktu. Ten przykład z frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration_tv.xml pokazuje dynamiczną maskę kanału, co oznacza, że menedżer zasad dotyczących dźwięku wysyła zapytanie o maski kanałów obsługiwane przez odbiornik HDMI po połączeniu.

<module name="primary" halVersion="2.0">
    <attachedDevices>
        <item>Speaker</item>
    </attachedDevices>
    <defaultOutputDevice>Speaker</defaultOutputDevice>
    <mixPorts>
        <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
        </mixPort>
        <mixPort name="direct" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT" />
        <mixPort name="tunnel" role="source"
                 flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_HW_AV_SYNC" />
   </mixPorts>
   <devicePorts>
        <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink" />
        <devicePort tagName="Out Aux Digital" type="AUDIO_DEVICE_OUT_AUX_DIGITAL" role="sink"
                    encodedFormats="AUDIO_FORMAT_AC3 AUDIO_FORMAT_IEC61937" />
    </devicePorts>
    <routes>
        <route type="mix" sink="Speaker" sources="primary output"/>
        <route type="mix" sink="Out Aux Digital" sources="primary output,direct,tunnel"/>
    </routes>
</module>

Możesz też podać stałą maskę kanału, np. AUDIO_CHANNEL_OUT_5POINT1. Mikser w AudioFlinger automatycznie konwertuje treści na dźwięk stereo, gdy zostaną wysłane na urządzenie audio, które nie obsługuje dźwięku wielokanałowego.

Kodeki multimediów

Upewnij się, że kodeki audio obsługiwane przez sprzęt i sterowniki są prawidłowo zadeklarowane w Twoim produkcie. Szczegółowe informacje znajdziesz w artykule Wyświetlanie kodeków w ramach frameworku.