Audio per auto e motori

Android Automotive OS (AAOS) si basa sullo stack audio Android di base per supportare i casi d'uso per il funzionamento come sistema di infotainment in un veicolo. AAOS è responsabile dei suoni di infotainment (ovvero contenuti multimediali, navigazione e comunicazioni), ma non è direttamente responsabile di suoni di avviso e avvisi con requisiti di disponibilità e tempistica rigorosi. Sebbene AAOS fornisca indicatori e meccanismi per aiutare il veicolo a gestire l'audio, alla fine è il veicolo a decidere quali suoni devono essere riprodotti per il conducente e i passeggeri, garantendo che gli avvisi sonori di sicurezza e quelli previsti dalle normative vengano ascoltati correttamente senza interruzioni.

Poiché Android gestisce l'esperienza multimediale del veicolo, le sorgenti multimediali esterne come il sintonizzatore radio devono essere rappresentate da app che possono gestire l'audio e gli eventi chiave multimediali per la sorgente.

Android 11 include le seguenti modifiche al supporto audio correlato all'automotive:

Suoni e stream di Android

I sistemi audio per auto gestiscono i seguenti suoni e stream:

Diagramma dell'architettura incentrata sugli stream

Figura 1. Diagramma dell'architettura incentrata sugli stream

Android gestisce i suoni provenienti dalle app Android, controllandole e inviandoli ai dispositivi di output nell'HAL in base al tipo di suono:

  • Gli stream logici, noti come sorgenti nella nomenclatura audio di base, sono contrassegnati con gli attributi audio.
  • Gli stream fisici, noti come dispositivi nella nomenclatura audio di base, non hanno informazioni sul contesto dopo il missaggio.

Per affidabilità, i suoni esterni (provenienti da fonti indipendenti come i segnali acustici di avviso della cintura di sicurezza) vengono gestiti al di fuori di Android, sotto l'HAL o addirittura in hardware separato. Gli implementatori di sistema devono fornire un mixer che accetti uno o più stream di input audio da Android e li combini in modo appropriato con le sorgenti audio esterne richieste dal veicolo.

L'implementazione HAL e il mixer esterno sono responsabili di garantire che i suoni esterni critici per la sicurezza vengano ascoltati e di mixare gli stream forniti da Android e inoltrarli a altoparlanti adatti.

Suoni Android

Le app possono avere uno o più player che interagiscono tramite le API Android standard (ad esempio AudioManager per il controllo dell'attenzione o MediaPlayer per lo streaming) per emettere uno o più stream logici di dati audio. Questi dati possono essere mono a un canale o surround 7.1, ma vengono instradati e trattati come un'unica sorgente. Lo stream dell'app è associato a AudioAttributes che forniscono al sistema suggerimenti su come deve essere espresso l'audio.

Gli stream logici vengono inviati tramite AudioService e instradati a uno (e solo uno) degli stream di output fisico disponibili, ciascuno dei quali è l'output di un mixer all'interno di AudioFlinger. Una volta che gli attributi audio sono stati mixati in uno stream fisico, non sono più disponibili.

Ogni stream fisico viene poi inviato all'HAL audio per il rendering sull'hardware. Nelle app per auto e motori, l'hardware di rendering può essere costituito da codec locali (come per i dispositivi mobili) o da un processore remoto sulla rete fisica del veicolo. In ogni caso, è compito dell'implementazione dell'HAL audio fornire i dati di sample effettivi e renderli udibili.

Stream esterni

Gli stream audio che non devono essere instradati tramite Android (per motivi di certificazione o di tempistica) possono essere inviati direttamente al mixer esterno. A partire da Android 11, l'HAL ora è in grado di richiedere l'attenzione per questi suoni esterni per informare Android in modo che possa intraprendere azioni appropriate, ad esempio mettere in pausa i contenuti multimediali o impedire ad altri di acquisire l'attenzione.

Se gli stream esterni sono sorgenti multimediali che devono interagire con l'ambiente audio generato da Android (ad esempio, interrompere la riproduzione di MP3 quando è attivo un sintonizzatore esterno), questi stream esterni devono essere rappresentati da un'app Android. Un'app di questo tipo richiederebbe l'attenzione audio per conto della sorgente multimediale anziché per l'HAL e risponderebbe alle notifiche di attenzione avviando/interrompendo la sorgente esterna in base alle necessità per rispettare le norme di attenzione di Android. L'app è responsabile anche della gestione di eventi chiave multimediali come riproduzione/pausa. Un meccanismo suggerito per controllare questi dispositivi esterni è HwAudioSource.

Dispositivi di output

A livello di Audio HAL, il tipo di dispositivo AUDIO_DEVICE_OUT_BUS fornisce un dispositivo di output generico da utilizzare nei sistemi audio dei veicoli. Il dispositivo di bus supporta le porte indirizzabili (in cui ogni porta è il punto di terminazione di uno stream fisico) e dovrebbe essere l'unico tipo di dispositivo di output supportato in un veicolo.

Un'implementazione di sistema può utilizzare una porta bus per tutti i suoni di Android, nel quale caso Android li mescola e li invia come un unico stream. In alternativa, l'HAL può fornire una porta bus per ogni CarAudioContext per consentire la consegna simultanea di qualsiasi tipo di audio. In questo modo, l'implementazione HAL consente di mixare e attenuare i diversi suoni in base alle esigenze.

L'assegnazione dei contesti audio ai dispositivi di output avviene tramite car_audio_configuration.xml.

Ingresso microfono

Durante l'acquisizione dell'audio, l'HAL audio riceve una chiamata openInputStream che include un argomento AudioSource che indica come deve essere elaborato l'input del microfono.

L'origine VOICE_RECOGNITION (in particolare l'Assistente Google) si aspetta uno stream del microfono stereo con un effetto di cancellazione dell'eco (se disponibile), ma senza alcuna altra elaborazione. Il beamforming dovrebbe essere eseguito dall'assistente.

Ingresso microfono multicanale

Per acquisire l'audio da un dispositivo con più di due canali (stereo), utilizza una maschera di indice di canale anziché una maschera di indice di posizione (ad esempio CHANNEL_IN_LEFT). Esempio:

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

Quando sono impostati sia setChannelMask sia setChannelIndexMask, AudioRecord utilizza solo il valore impostato da setChannelMask (massimo due canali).

Acquisizione simultanea

A partire da Android 10, il framework Android supporta la cattura simultanea degli input, ma con limitazioni per proteggere la privacy dell'utente. Nell'ambito di queste limitazioni, le sorgenti virtuali comeAUDIO_SOURCE_FM_TUNER vengono ignorate e, di conseguenza, possono essere acquisite contemporaneamente insieme a un input normale (come il microfono). HwAudioSources non sono considerati parte delle limitazioni di acquisizione simultanea.

Le app progettate per funzionare con dispositivi AUDIO_DEVICE_IN_BUS o con dispositivi AUDIO_DEVICE_IN_FM_TUNER secondari devono basarsi sull'identificazione esplicita di questi dispositivi e sull'utilizzo di AudioRecord.setPreferredDevice() per bypassare la logica di selezione della sorgente predefinita di Android.

Utilizzi audio

AAOS utilizza principalmente AudioAttributes.AttributeUsages per il routing, la regolazione del volume e la gestione dell'attenzione. Gli utilizzi rappresentano il "perché" lo stream viene riprodotto. Pertanto, tutte le richieste di stream e di attenzione audio devono specificare un utilizzo per la riproduzione audio. Se non viene impostato specificamente durante la creazione di un oggetto AudioAttributes, per l'utilizzo verrà utilizzato il valore predefinito USAGE_UNKNOWN. Anche se al momento viene trattato come USAGE_MEDIA, non bisogna fare affidamento su questo comportamento per la riproduzione dei contenuti multimediali.

Utilizzi del sistema

In Android 11 sono stati introdotti gli utilizzi di sistema. Questi utilizzi si comportano in modo simile a quelli stabiliti in precedenza, tranne per il fatto che richiedono l'utilizzo delle API di sistema oltre a android.permission.MODIFY_AUDIO_ROUTING. I nuovi utilizzi del sistema sono:

  • USAGE_EMERGENCY
  • USAGE_SAFETY
  • USAGE_VEHICLE_STATUS
  • USAGE_ANNOUNCEMENT

Per creare un AudioAttributes con un utilizzo del sistema, utilizza AudioAttributes.Builder#setSystemUsage instead of setUsage. La chiamata a questo metodo con un utilizzo non di sistema causerà l'emissione di un IllegalArgumentException. Inoltre, se su un generatore sono stati impostati sia l'utilizzo sia l'utilizzo del sistema, verrà generato un errore IllegalArgumentException durante la compilazione.

Per controllare l'utilizzo associato a un'istanza AudioAttributes, chiama AudioAttributes#getSystemUsage. Restituisce l'utilizzo o l'utilizzo del sistema associato.

Contesti audio

Per semplificare la configurazione dell'audio AAOS, gli utilizzi simili sono stati raggruppati in CarAudioContext. Questi contesti audio vengono utilizzati in tutto CarAudioService per definire il routing, i gruppi di volume e la gestione dell'attenzione audio.

I contesti audio in Android 11 sono:

CarAudioContext AttributeUsages associati
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

Mappatura tra contesti e utilizzi audio. Le righe evidenziate sono per i nuovi utilizzi del sistema.

Audio multizona

Il settore auto e motori offre una nuova serie di casi d'uso relativi agli utenti simultanei che interagiscono con la piattaforma e vogliono consumare contenuti multimediali separati. Ad esempio, un conducente può riprodurre musica nell'abitacolo mentre i passeggeri seduti sui sedili posteriori guardano un video di YouTube sul display posteriore. L'audio multizona consente di farlo consentendo la riproduzione simultanea di diverse origini audio in aree diverse del veicolo.

L'audio multizona, disponibile a partire da Android 10, consente agli OEM di configurare l'audio in zone separate. Ogni zona è un insieme di dispositivi all'interno del veicolo con i propri gruppi di volume, la configurazione del routing per i contesti e la gestione dell'attenzione. In questo modo, la cabina principale può essere configurata come una zona audio, mentre le prese per cuffie del display posteriore possono essere configurate come una seconda zona.

Le zone sono definite nell'ambito di car_audio_configuration.xml. CarAudioService legge quindi la configurazione e aiuta AudioService a indirizzare gli stream audio in base alla zona associata. Ogni zona definisce comunque le regole per il routing in base ai contesti e all'UID delle applicazioni. Quando viene creato un player, CarAudioService determina a quale zona è associato e, in base all'utilizzo, a quale dispositivo AudioFlinger deve instradare l'audio.

Anche l'attenzione viene mantenuta in modo indipendente per ogni zona audio. In questo modo, le applicazioni in zone diverse possono produrre audio in modo indipendente senza interferire tra loro, rispettando al contempo le modifiche dell'attenzione all'interno della loro zona. CarZonesAudioFocus all'interno di CarAudioService è responsabile della gestione dell'attenzione per ogni zona.

Configurare l'audio multizona

Figura 2. Configurare l'audio multizona

HAL audio

Le implementazioni audio per auto si basano sull'HAL Android Audio standard, che include quanto segue:

  • IDevice.hal. Crea stream di input e output, gestisci il volume principale e la disattivazione dell'audio e utilizza:
    • createAudioPatch. Per creare patch esterne-esterne tra dispositivi.
    • IDevice.setAudioPortConfig() per fornire il volume per ogni stream fisico.
  • IStream.hal. Insieme alle varianti di input e output, gestisce lo streaming dei campioni audio verso e dall'hardware.

Tipi di dispositivi per auto e motori

I seguenti tipi di dispositivi sono pertinenti per le piattaforme per auto e motori.

Tipo di dispositivo Descrizione
AUDIO_DEVICE_OUT_BUS Uscita principale da Android (in questo modo tutto l'audio di Android viene fornito al veicolo). Utilizzato come indirizzo per distinguere gli stream per ciascun contesto.
AUDIO_DEVICE_OUT_TELEPHONY_TX Utilizzato per l'audio inviato alla radio cellulare per la trasmissione.
AUDIO_DEVICE_IN_BUS Utilizzato per input non classificati in altro modo.
AUDIO_DEVICE_IN_FM_TUNER Utilizzato solo per l'input radio di trasmissione.
AUDIO_DEVICE_IN_TV_TUNER Utilizzato per un dispositivo TV, se presente.
AUDIO_DEVICE_IN_LINE Utilizzato per il jack di ingresso AUX.
AUDIO_DEVICE_IN_BLUETOOTH_A2DP Musica ricevuta tramite Bluetooth.
AUDIO_DEVICE_IN_TELEPHONY_RX Utilizzato per l'audio ricevuto dalla radio cellulare associata a una telefonata.

Configurazione dei dispositivi audio

I dispositivi audio visibili ad Android devono essere definiti in /audio_policy_configuration.xml, che include i seguenti componenti:

  • nome del modulo. Supporta "principale" (utilizzato per i casi d'uso nel settore auto e motori), "A2DP", "remote_submix" e "USB". Il nome del modulo e il driver audio corrispondente devono essere compilati in audio.primary.$(variant).so.
  • devicePorts. Contiene un elenco di descrittori di dispositivi per tutti i dispositivi di input e output (inclusi i dispositivi collegati in modo permanente e i dispositivi rimovibili) a cui è possibile accedere da questo modulo.
    • Per ogni dispositivo di output, puoi definire il controllo del guadagno costituito da valori min/max/default/step in millibel (1 millibel = 1/100 dB = 1/1000 bel).
    • L'attributo address di un'istanza devicePort può essere utilizzato per trovare il dispositivo, anche se sono presenti più dispositivi con lo stesso tipo di dispositivo di AUDIO_DEVICE_OUT_BUS.
  • mixPorts. Contiene un elenco di tutti gli stream di input e output esposti dall'HAL audio. Ogni istanza di mixPort può essere considerata come uno stream fisico per Android AudioService.
  • percorsi. Definisce un elenco di possibili connessioni tra dispositivi di input e di output o tra stream e dispositivo.

Il seguente esempio definisce un bus0_phone_out del dispositivo di uscita in cui tutti gli stream audio di Android vengono miscelati da mixer_bus0_phone_out. Il percorso prende lo stream di output di mixer_bus0_phone_out e lo invia al dispositivobus0_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>