Dźwięk samochodowy

System operacyjny Android Automotive (AAOS) opiera się na podstawowym pakiecie audio Androida, aby obsługiwać przypadki użycia systemu multimedialnego w samochodzie. AAOS odpowiada za dźwięki systemów informacyjno-rozrywkowych (czyli dźwięki związane z multimediami, nawigacją i komunikacją), ale nie odpowiada bezpośrednio za sygnały dźwiękowe i ostrzeżenia, które mają ścisłe wymagania dotyczące dostępności i czasu. Chociaż AAOS udostępnia sygnały i mechanizmy, które pomagają pojazdowi zarządzać dźwiękiem, to ostatecznie to pojazd decyduje, jakie dźwięki powinny być odtwarzane dla kierowcy i pasażerów, aby zapewnić prawidłowe odtwarzanie dźwięków związanych z bezpieczeństwem i dźwięków regulowanych bez zakłóceń.

Ponieważ Android zarządza multimediami w samochodzie, zewnętrzne źródła multimediów, takie jak tuner radiowy, powinny być reprezentowane przez aplikacje, które mogą obsługiwać zdarzenia dotyczące skupienia na dźwięku i kluczy multimedialnych dla źródła.

Android 11 wprowadza następujące zmiany w obsługiwaniu dźwięku w samochodach:

Dźwięki i strumienie z Androida

Systemy audio w pojazdach obsługują te dźwięki i strumienie:

Schemat architektury skoncentrowanej na strumieniu

Rysunek 1. Schemat architektury skoncentrowanej na strumieniu

Android zarządza dźwiękami pochodzącymi z aplikacji, kontrolując te aplikacje i przekierowując ich dźwięki do urządzeń wyjściowych w HAL na podstawie typu dźwięku:

  • Strumienie logiczne, czyli źródła w podstawowej nomenklaturze audio, są oznaczane za pomocą atrybutów audio.
  • Stremy fizyczne, czyli urządzenia w podstawowej nomenklaturze audio, nie zawierają informacji kontekstowych po zmiksowaniu.

Ze względu na niezawodność dźwięki zewnętrzne (pochodzące z niezależnych źródeł, takich jak sygnały ostrzegawcze dotyczące pasów bezpieczeństwa) są zarządzane poza Androidem, poniżej HAL lub nawet na osobnym sprzęcie. Implementatorzy systemu muszą zapewnić mikser, który przyjmuje co najmniej 1 strumień wejściowy dźwięku z Androida, a następnie łączy te strumienie w odpowiednim sposób z zewnętrznych źródeł dźwięku wymaganych przez pojazd.

Implementacja HAL i zewnętrzny mikser odpowiadają za to, aby dźwięki zewnętrzne istotne z punktu widzenia bezpieczeństwa były słyszalne, a także za miksowanie strumieni danych udostępnianych przez Androida i przekierowywanie ich do odpowiednich głośników.

Dźwięki w Androidzie

Aplikacje mogą mieć co najmniej 1 odtwarzacz, który współpracuje ze standardowymi interfejsami API Androida (np. AudioManager do kontrolowania ostrości lub MediaPlayer do strumieniowego przesyłania danych), aby emitować co najmniej 1 logiczny strumień danych audio. Te dane mogą być mono mono lub dźwiękiem przestrzennym 7.1, ale są kierowane i traktowane jako pojedyncze źródło. Strumień aplikacji jest powiązany z atrybutami audio, które podpowiadają systemowi, jak powinien brzmieć dźwięk.

Strumienie logiczne są wysyłane przez AudioService i przekierowywane do jednego (i tylko jednego) z dostępnych fizycznych strumieni wyjściowych, z których każdy jest wyjściem miksera w AudioFlinger. Gdy atrybuty dźwiękowe zostaną zmiksowane do fizycznego strumienia, nie są już dostępne.

Następnie każdy fizyczny strumień jest dostarczany do Audio HAL w celu renderowania na sprzęcie. W przypadku aplikacji samochodowych sprzęt do renderowania może być lokalnym kodekiem (podobnie jak w przypadku urządzeń mobilnych) lub zdalnym procesorem w ramach fizycznej sieci pojazdu. W obu przypadkach zadaniem implementacji interfejsu Audio HAL jest dostarczenie rzeczywistych danych próbkowania i ustawienie ich tak, aby były słyszalne.

strumieniowanie zewnętrzne,

Strumienie dźwięku, które nie powinny być kierowane przez Androida (ze względów certyfikacyjnych lub ze względów związanych z synchronizacją), mogą być wysyłane bezpośrednio do zewnętrznego miksera. Od Androida 11 interfejs HAL może żądać skupienia na tych zewnętrznych dźwiękach, aby poinformować Androida, aby mógł podjąć odpowiednie działania, takie jak wstrzymanie multimediów lub uniemożliwienie innym aplikacji przejęcia kontroli.

Jeśli strumienie zewnętrzne to źródła multimediów, które powinny wchodzić w interakcje ze środowiskiem dźwiękowym generowanym przez Androida (np. zatrzymywać odtwarzanie MP3, gdy włączony jest tuner zewnętrzny), powinny być reprezentowane przez aplikację na Androida. Taka aplikacja będzie prosić o skupienie dźwięku w imieniu źródła multimediów zamiast HAL i będzie odpowiadać na powiadomienia o skupieniu, uruchamiając lub zatrzymując źródło zewnętrzne w sposób zgodny z zasadami Androida dotyczącymi skupienia. Aplikacja jest też odpowiedzialna za obsługę kluczowych zdarzeń związanych z multimediami, takich jak odtwarzanie/wstrzymanie. Jednym z zalecanych mechanizmów sterowania takimi urządzeniami zewnętrznymi jest HwAudioSource.

Urządzenia wyjściowe

Na poziomie Audio HAL typ urządzenia AUDIO_DEVICE_OUT_BUSstanowi ogólne urządzenie wyjściowe do użytku w systemach audio pojazdu. Urządzenie z interfejsem magistrali obsługuje adresowalne porty (gdzie każdy port jest punktem końcowym fizycznego strumienia) i ma być jedynym obsługiwanym typem urządzenia wyjściowego w pojazdzie.

Implementacja systemu może używać jednego portu magistrali do wszystkich dźwięków Androida. W takim przypadku Android miksuje wszystkie dźwięki i przesyła je jako jeden strumień. Alternatywnie HAL może udostępnić jeden port magistrali dla każdego CarAudioContext, aby umożliwić jednoczesną dostawę dowolnego typu dźwięku. Dzięki temu implementacja HAL może miksować i zmieniać głośność różnych dźwięków zgodnie z potrzebami.

Przypisywanie kontekstów audio do urządzeń wyjściowych odbywa się za pomocą car_audio_configuration.xml.

Dane wejściowe z mikrofonu

Podczas rejestrowania dźwięku interfejs Audio HAL otrzymuje wywołanie openInputStream, które zawiera argument AudioSource wskazujący, jak przetwarzać dane wejściowe z mikrofonu.

Źródło VOICE_RECOGNITION (w szczególności Asystent Google) oczekuje strumienia mikrofonu stereo, który zawiera efekt redukcji echa (jeśli jest dostępny), ale nie ma żadnego innego przetwarzania. Beamforming powinien być wykonywany przez Asystenta.

Wielokanałowy mikrofon

Aby rejestrować dźwięk z urządzenia z więcej niż 2 kanałami (stereo), użyj maski indeksu kanału zamiast maski indeksu pozycyjnego (np. CHANNEL_IN_LEFT). Przykład:

final AudioFormat audioFormat = new AudioFormat.Builder()
    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    .setSampleRate(44100)
    .setChannelIndexMask(0xf /* 4 channels, 0..3 */)
    .build();
final AudioRecord audioRecord = new AudioRecord.Builder()
    .setAudioFormat(audioFormat)
    .build();
audioRecord.setPreferredDevice(someAudioDeviceInfo);

Gdy ustawisz zarówno setChannelMask, jak i setChannelIndexMask, AudioRecord będzie używać tylko wartości ustawionej przez setChannelMask (maksymalnie 2 kanały).

Równoczesne przechwytywanie

Od Androida 10 platforma Android obsługuje jednoczesne rejestrowanie danych wejściowych, ale z ograniczeniami, które chronią prywatność użytkownika. W ramach tych ograniczeń źródła wirtualne, takie jak AUDIO_SOURCE_FM_TUNER, są ignorowane, dzięki czemu można je rejestrować jednocześnie z normalnym wejściem (np. mikrofonem). HwAudioSources nie są też uwzględniane w ramach ograniczeń dotyczących jednoczesnego przechwytywania.

Aplikacje zaprojektowane do działania na urządzeniach AUDIO_DEVICE_IN_BUS lub na urządzeniach pomocniczych AUDIO_DEVICE_IN_FM_TUNER muszą wyraźnie identyfikować te urządzenia i korzystać z funkcji AudioRecord.setPreferredDevice(), aby ominąć domyślną logikę wyboru źródła w Androidzie.

Zastosowania dźwięku

AAOS wykorzystuje głównie AudioAttributes.AttributeUsages do routingu, regulacji głośności i zarządzania ostrością. Użycia to reprezentacja „dlaczego” strumień jest odtwarzany. Dlatego wszystkie żądania dotyczące strumieni i żądania dotyczące dźwięku powinny określać sposób odtwarzania dźwięku. Jeśli podczas tworzenia obiektu AudioAttributes nie zostanie określony, domyślnie zostanie ustawiona wartość USAGE_UNKNOWN. Obecnie jest ono traktowane tak samo jak USAGE_MEDIA, ale nie należy polegać na tym podczas odtwarzania multimediów.

Wykorzystanie przez system

W Androidzie 11 wprowadzono użycie systemu. Te zastosowania działają podobnie do wcześniej ustalonych zastosowań, z tym wyjątkiem, że wymagają interfejsów API systemu i interfejsu android.permission.MODIFY_AUDIO_ROUTING. Nowe zastosowania systemu:

  • USAGE_EMERGENCY
  • USAGE_SAFETY
  • USAGE_VEHICLE_STATUS
  • USAGE_ANNOUNCEMENT

Aby utworzyć AudioAttributes z użyciem systemu, użyj AudioAttributes.Builder#setSystemUsage zamiast setUsage. Wywołanie tej metody w celu niesystematycznym spowoduje wyjątek IllegalArgumentException. Jeśli w kreatorze ustawisz zarówno użycie systemu, jak i użycie, podczas kompilowania wystąpi błąd IllegalArgumentException.

Aby sprawdzić, jakie użycie jest powiązane z instancją AudioAttributes, wywołaj funkcję AudioAttributes#getSystemUsage. Zwraca powiązane dane o korzystaniu z aplikacji lub systemu.

Konteksty audio

Aby uprościć konfigurację dźwięku w AAOS, podobne zastosowania zostały pogrupowane w grupę CarAudioContext. Te konteksty audio są używane w całym CarAudioService do definiowania routingu, grup głośności i zarządzania skupieniem dźwięku.

Konteksty dźwięku w Androidzie 11:

CarAudioContext Powiązane atrybutyUsages
MUSIC UNKNOWN, GAME, MEDIA
NAVIGATION ASSISTANCE_NAVIGATION_GUIDANCE
VOICE_COMMAND ASSISTANT, ASSISTANCE_ACCESSIBILITY
CALL_RING NOTIFICATION_RINGTONE
CALL VOICE_COMMUNICATION, VOICE_COMMUNICATION_SIGNALING
ALARM ALARM
NOTIFICATION NOTIFICATION, NOTIFICATION_*
SYSTEM_SOUND ASSISTANCE_SONIFICATION
EMERGENCY EMERGENCY
SAFETY SAFETY
VEHICLE_STATUS VEHICLE_STATUS
ANNOUNCEMENT ANNOUNCEMENT

mapowanie kontekstów i zastosowanie dźwięku; Wyróżnione wiersze dotyczą nowych użytków systemu.

Dźwięk wielostrefowy

W przypadku branży motoryzacyjnej pojawia się nowy zestaw przypadków użycia dotyczących jednoczesnych użytkowników, którzy korzystają z platformy i chcą korzystać z różnych mediów. Na przykład kierowca może odtwarzać muzykę w kabinie, podczas gdy pasażerowie na tylnym siedzeniu oglądają film w YouTube na wyświetlaczu z tyłu. Umożliwia to dźwięk wielostrefowy, który pozwala na odtwarzanie różnych źródeł dźwięku w różnych obszarach pojazdu jednocześnie.

Tryb dźwięku wielostrefowego, który pojawił się w Androidzie 10, umożliwia producentom urządzeń z systemem Android konfigurowanie dźwięku w oddzielnych strefach. Każda strefa to zbiór urządzeń w pojazdzie z własnymi grupami głośności, konfiguracją routingu dla kontekstów i zarządzaniem skupieniem. W ten sposób kabina główna może być skonfigurowana jako jedna strefa audio, a gniazda słuchawek na tylnym ekranie jako druga strefa.

Strefy są definiowane w ramach car_audio_configuration.xml. CarAudioService odczytuje konfigurację i pomoże usłudze AudioService przekierowywać strumienie audio na podstawie powiązanej strefy. Każda strefa nadal definiuje reguły routingu na podstawie kontekstów i identyfikatorów aplikacji. Gdy tworzony jest odtwarzacz, CarAudioService określa, z jaką strefą jest powiązany, a następnie na podstawie sposobu użycia określa, na które urządzenie AudioFlinger powinien przekierować dźwięk.

Ustawienie to jest również utrzymywane niezależnie w przypadku każdej strefy dźwięku. Dzięki temu aplikacje w różnych strefach mogą niezależnie od siebie generować dźwięk bez zakłócania się nawzajem, a jednocześnie uwzględniać zmiany w fokusie w swojej strefie. CarZonesAudioFocusCarAudioService odpowiada za zarządzanie fokusem w poszczególnych strefach.

Konfigurowanie dźwięku wielostrefowego

Rysunek 2. Konfigurowanie dźwięku wielostrefowego

Interfejs HAL dźwięku

Implementacje audio w samochodach korzystają ze standardowego interfejsu HAL Androida Audio, który obejmuje:

  • IDevice.hal. Tworzy strumienie wejściowe i wyjściowe, obsługuje główną głośność i wyciszanie oraz używa:
    • createAudioPatch. Aby tworzyć poprawki zewnętrzne między urządzeniami.
    • IDevice.setAudioPortConfig(), aby określić głośność dla każdego fizycznego strumienia.
  • IStream.hal. Wraz z wariantami wejścia i wyjścia zarządza strumieniowaniem próbek audio do i z urządzenia.

Typy urządzeń samochodowych

W przypadku platform samochodowych istotne są te typy urządzeń:

Typ urządzenia Opis
AUDIO_DEVICE_OUT_BUS Podstawowe wyjście z Androida (w ten sposób wszystkie dźwięki z Androida są dostarczane do pojazdu). Służy jako adres do rozróżniania strumieni w ramach każdego kontekstu.
AUDIO_DEVICE_OUT_TELEPHONY_TX Używany do dźwięku kierowanego do radia komórkowego w celu transmisji.
AUDIO_DEVICE_IN_BUS Używany w przypadku danych wejściowych, które nie zostały zaklasyfikowane w inny sposób.
AUDIO_DEVICE_IN_FM_TUNER Służy tylko do wprowadzania danych z radia nadawczego.
AUDIO_DEVICE_IN_TV_TUNER Używany w przypadku telewizora, jeśli jest dostępny.
AUDIO_DEVICE_IN_LINE Służy do gniazda wejściowego AUX.
AUDIO_DEVICE_IN_BLUETOOTH_A2DP Muzyka odbierana przez Bluetooth.
AUDIO_DEVICE_IN_TELEPHONY_RX Służy do odtwarzania dźwięku z radia komórkowego powiązanego z połączeniem telefonicznym.

Konfigurowanie urządzeń audio

Urządzenia audio widoczne dla Androida muszą być zdefiniowane w pliku /audio_policy_configuration.xml, który zawiera te komponenty:

  • nazwa modułu. Obsługuje „primary” (używane w przypadku zastosowań motoryzacyjnych), „A2DP”, „remote_submix” i „USB”. Nazwa modułu i odpowiadający mu sterownik audio powinny zostać skompilowane do audio.primary.$(variant).so.
  • devicePorts. Zawiera listę deskryptorów urządzeń dla wszystkich urządzeń wejściowych i wyjściowych (w tym urządzeń trwale podłączonych i wymiennych), do których można uzyskać dostęp z tego modułu.
    • W przypadku każdego urządzenia wyjściowego możesz zdefiniować kontrolę wzmocnienia, która składa się z wartości min/max/domyślna/krok w miliblach (1 milibel = 1/100 dB = 1/1000 bel).
    • Atrybutu adresu w przypadku instancji devicePort można użyć do znalezienia urządzenia, nawet jeśli jest kilka urządzeń tego samego typu co AUDIO_DEVICE_OUT_BUS.
  • mixPorts. Zawiera listę wszystkich strumieni wyjściowych i wejściowych udostępnionych przez HAL audio. Każda instancja mixPort może być traktowana jako fizyczny strumień do usługi Android AudioService.
  • tras. Określa listę możliwych połączeń między urządzeniami wejściowymi i wyjściowymi lub między strumieniem a urządzeniem.

W tym przykładzie definiujemy wyjściowe urządzenie bus0_phone_out, w którym wszystkie strumienie audio z Androida są miksowane przez mixer_bus0_phone_out. Trasa przenosi strumień wyjściowy z mixer_bus0_phone_out na urządzenie bus0_phone_out.

<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>bus0_phone_out</item>
<defaultOutputDevice>bus0_phone_out</defaultOutputDevice>
            <mixPorts>
                <mixPort name="mixport_bus0_phone_out"
                         role="source"
                         flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="bus0_phone_out"
                            role="sink"
                            type="AUDIO_DEVICE_OUT_BUS"
                            address="BUS00_PHONE">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                    <gains>
                        <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                minValueMB="-8400"
                                maxValueMB="4000"
                                defaultValueMB="0"
                                stepValueMB="100"/>
                    </gains>
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="bus0_phone_out"
                       sources="mixport_bus0_phone_out"/>
            </routes>
        </module>
    </modules>
</audioPolicyConfiguration>