HAL per il controllo audio

L'HAL di controllo audio è stato introdotto in Android 9 per supportare i casi d'uso audio pertinenti al settore auto e motori. A partire da Android 14, l'HAL di controllo audio supporta:

  • Dissolvenza e bilanciamento
  • Richiesta di attenzione audio HAL
  • Disattivazione audio e riduzione del volume del dispositivo
  • Modifiche al guadagno del dispositivo audio
  • Modifiche alla configurazione della porta audio

La Figura 1 mostra una panoramica generale dell'architettura del servizio audio per auto, in cui il servizio audio per auto comunica con l'HAL di controllo audio.

Configurare l'audio multizona

Figura 1. Configura l'audio multizona.

Dissolvenza e bilanciamento audio

La versione 1 dell'HAL di controllo audio HIDL è stata introdotta in Android 9 per supportare l'attenuazione e il bilanciamento audio nei casi di utilizzo nel settore auto e motori. A parte gli effetti audio generici già forniti in Android, questo meccanismo consente alle app di sistema di impostare il bilanciamento audio e la dissolvenza tramite le APICarAudioManager:

class CarAudioManager {
       /**
       *   Adjust the relative volume in the front vs back of the vehicle cabin.
       *
       *   @param value in the range -1.0 to 1.0 for fully toward the back through
       *   fully toward the front. 0.0 means evenly balanced.
       */
       @SystemApi
       @RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
       public void setFadeTowardFront(float value);

       /**
       *   Adjust the relative volume on the left vs right side of the vehicle cabin.
       *
       *   @param value in the range -1.0 to 1.0 for fully toward the left through
       *   fully toward the right. 0.0 means evenly balanced.
       */
       @SystemApi
       @RequiresPermission(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME)
       public void setBalanceTowardRight(float value);
}

Una volta chiamate queste API, le rispettive API HAL di controllo audio vengono chiamate dal servizio audio dell'auto:

interface IAudioControl {
       /**
       *   Control the right/left balance setting of the car speakers.
       */
       oneway setBalanceTowardRight(float value);

       /**
       *   Control the fore/aft fade setting of the car speakers.
       */
       oneway setFadeTowardFront(float value);
}

L'API è disponibile su tutte le versioni dell'HAL di controllo audio, inclusa la nuova interfaccia HAL AIDL.

Richiesta di attenzione audio da HAL

AAOS, come Android, si basa sulla partecipazione attiva delle app in modalità di attenzione audio per gestire la riproduzione audio nelle auto. Le informazioni relative allo stato attivo vengono utilizzate per gestire gli stream da controllare per il volume e la disattivazione audio. Di conseguenza, per espandere ulteriormente l'attenzione all'audio e per offrire una migliore integrazione dei suoni specifici dell'auto nell'esperienza Android, in Android 11 sono stati introdotti i seguenti attributi audio:

  • EMERGENCY
  • SAFETY
  • VEHICLE_STATUS
  • ANNOUNCEMENT

Oltre a questa modifica, è stato aggiunto un meccanismo per consentire ai suoni provenienti da outside Android di partecipare alle richieste di attenzione audio. Pertanto, è stata introdotta la versione 2 dell'HAL di controllo audio HIDL per consentire richieste di messa a fuoco provenienti dall'esterno di Android:

interface IAudioControl {
       /**
       *   Registers focus listener to be used by HAL for requesting and
       *   abandoning audio focus.
       *   @param listener the listener interface
       *   @return closeHandle A handle to unregister observer.
       */
       registerFocusListener(IFocusListener listener)
       generates (ICloseHandle closeHandle);

       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   @param usage The audio usage associated with the focus change
       *   @param zoneId The identifier for the audio zone that the HAL is
       *   playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred
       */
       oneway onAudioFocusChange(bitfield<AudioUsage> usage, int32_t zoneId,
       bitfield<AudioFocusChange> focusChange);
}

Dove IFocusListener è definito come:

interface IFocusListener {
       /**
       *   Called whenever HAL is requesting focus as it is starting to play
       *   audio of a given usage in a specified zone.
       *
       *   @param usage The audio usage associated with the focus request
       *    {@code AttributeUsage}
       *   @param zoneId The identifier for the audio zone where the HAL is
       *    requesting focus
       *   @param focusGain The AudioFocusChange associated with this request.
       */
       oneway requestAudioFocus(bitfield<AudioUsage> usage,
       int32_t zoneId, bitfield<AudioFocusChange> focusGain);
       /**
       *   Called whenever HAL is abandoning focus as it is finished playing audio
       *   of a given usage in a specific zone.
       *
       *   @param usage The audio usage for which the HAL is abandoning focus
       *    {@code AttributeUsage}
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       */
       oneway abandonAudioFocus(bitfield<AudioUsage> usage, int32_t zoneId);
}

Le API sopra indicate possono essere utilizzate rispettivamente per richiedere e abbandonare l'attenzione audio dall'HAL. In risposta, il servizio audio dell'auto prende in considerazione la richiesta di attenzione audio e inoltra i risultati in modo asincrono al metodoIAudioControl#onAudioFocusChange.

Questa API può essere utilizzata anche per monitorare le modifiche alla richiesta di attenzione audio che proviene dall'HAL di controllo audio. In generale, qualsiasi richiesta di attenzione audio in attesa proveniente dall'HAL è considerata attiva, il che è diverso da una richiesta di attenzione audio proveniente da Android, in cui viene considerata attiva solo la riproduzione di una traccia audio attiva corrispondente.

Esegui la migrazione dall'HAL di controllo audio HIDL all'HAL di controllo audio AIDL

Con l'avvento di AIDL e la migrazione obbligatoria in Android 12 (per saperne di più, consulta AIDL per gli HAL), è stata eseguita la migrazione dell'HAL di controllo audio ad AIDL. Per le API HIDL di controllo audio esistenti della versione 2, la migrazione ha richiesto aggiornamenti minori ai metodi esistenti:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   @param usage The audio usage associated with the focus change
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone that the HAL is
       *        playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred.
       */
       oneway void onAudioFocusChange(in String usage, in int zoneId,
              in AudioFocusChange focusChange);
       /**
       *   Registers focus listener to be used by HAL for requesting and
       *   abandoning audio focus.
       *   @param listener the listener interface.
       */
       oneway void registerFocusListener(in IFocusListener listener);
       /**
       *   Control the right/left balance setting of the car speakers.
       */
       oneway void setBalanceTowardRight(in float value);
       /**
       *   Control the fore/aft fade setting of the car speakers.
       */
       oneway void setFadeTowardFront(in float value);
}

E il IFocusListener corrispondente:

       interface IFocusListener {
       /**
       *   Called whenever HAL is abandoning focus as it is finished playing audio
       *   of a given usage in a specific zone.
       *
       *   @param usage The audio usage for which the HAL is abandoning focus
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone that the HAL
       *        abandoning focus
       */
       oneway void abandonAudioFocus(in String usage, in int zoneId);
       /**
       *   Called whenever HAL is requesting focus as it is starting to play audio
       *        of a given usage in a specified zone.
       *
       *   @param usage The audio usage associated with the focus request
       *        {@code AttributeUsage}. See {@code audioUsage} in
       *        audio_policy_configuration.xsd for the list of allowed values.
       *   @param zoneId The identifier for the audio zone where the HAL is
       *        requesting focus
       *   @param focusGain The AudioFocusChange associated with this request.
       */
       oneway void requestAudioFocus(in String usage, in int zoneId,
              in AudioFocusChange focusGain);
}

Disattivazione del volume del gruppo

Android 12 ha introdotto la disattivazione del volume del gruppo per consentire un controllo più completo della disattivazione dell'audio durante le interazioni audio dell'utente. In questo modo, l'HAL di controllo audio può ricevere eventi di disattivazione audio intercettati dal servizio audio dell'auto.

Per attivare la funzionalità, gli OEM devono impostare il valore audioUseCarVolumeGroupMuting su true nel servizio auto config.xml:

<!-- Configuration to enable muting of individual volume groups.
If this is set to false, muting of individual volume groups is disabled,
instead muting will toggle master mute. If this is set to true, car volume
group muting is enabled and each individual volume group can be muted separately. -->
<bool name="audioUseCarVolumeGroupMuting">true</bool>

Prima di Android 13, la configurazione doveva essere sovrascritta con un overlay delle risorse di runtime per packages/services/Car/service/res/values/config.xml (per saperne di più, consulta Personalizzare la build con gli overlay delle risorse). Da Android 13, puoi utilizzare gli overlay delle risorse di runtime per modificare un valore di configurazione. Per scoprire di più, consulta Modificare il valore delle risorse di un'app in fase di esecuzione.

Le app di sistema possono determinare se la funzionalità è abilitata utilizzando l'APICarAudioManager#isAudioFeatureEnabled. Il parametro passato deve essere la costante CarAudioManager.AUDIO_FEATURE_VOLUME_GROUP_MUTING. Il metodo restituisce true se la funzionalità è attivata sul dispositivo, altrimenti false.

Oltre ad attivare la funzionalità audioUseCarVolumeGroupMuting, l'HAL di controllo audio AIDL deve implementare il meccanismo di disattivazione del volume del gruppo:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in output devices that the HAL should apply
       *   muting to.
       *
       *   This will be called in response to changes in audio mute state for each
       *   volume group and will include a {@link MutingInfo} object per audio
       *   zone that experienced a mute state event.
       *
       *   @param mutingInfos an array of {@link MutingInfo} objects for the audio
       *   zones where audio mute state has changed.
       */
       oneway void onDevicesToMuteChange(in MutingInfo[] mutingInfos);
}

Dove le informazioni sulla disattivazione dell'audio contengono le informazioni pertinenti sulla disattivazione dell'audio per l'impianto audio:

parcelable MutingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be muted.
       */
       String[] deviceAddressesToMute;
       /**
       *   List of addresses for audio output devices that were previously be
       *   muted and should now be unmuted.
       */
       String[] deviceAddressesToUnmute;
}

AAOS dispone di due diversi meccanismi di disattivazione dell'audio, in base a:

  • Eventi chiave che utilizzano il codice audio KEYCODE_VOLUME_MUTE.

  • Chiamate dirette al servizio audio per auto utilizzando l'API di disattivazione audio per auto,CarAudioManager#setVolumeGroupMute.

Se abilitati, entrambi i meccanismi attivano la disattivazione dell'audio della chiamata nell'HAL di controllo audio.

Attenuazione automatica dell'audio dell'auto

Android 12 ha introdotto il silenziamento dell'audio dell'auto per ottimizzare il controllo della riproduzione simultanea degli stream audio. In questo modo, gli OEM possono implementare il proprio comportamento di attenuazione in base alla configurazione audio fisica di un'auto e allo stato di riproduzione corrente, come stabilito dal servizio audio dell'auto.

Il meccanismo di attenuazione si basa sulle modifiche alla pila di stato attivo audio. Ogni volta che si verifica una variazione di messa a fuoco (richiesta di messa a fuoco o abbandono della messa a fuoco), l'HAL di controllo audio viene informato. Analogamente al supporto della disattivazione del volume del gruppo di auto, la funzionalità di attenuazione dell'audio dell'auto può essere attivata con il flag di configurazione audioUseHalDuckingSignals:

<!-- Configuration to enable IAudioControl#onDevicesToDuckChange API to
inform HAL when to duck. If this is set to true, the API will receive signals
indicating which output devices to duck as well as what usages are currently
holding focus. If set to false, the API will not be called. -->
<bool name="audioUseHalDuckingSignals">true</bool>

Per attivare la funzionalità, l'HAL di controllo audio AIDL deve implementare la logica pertinente con il segnale ricevuto dal servizio audio dell'auto:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in output devices that the HAL should apply
       *   ducking to.
       *
       *   This will be called in response to changes in audio focus, and will
       *   include a {@link DuckingInfo} object per audio zone that experienced
       *   a change in audo focus.
       *
       *   @param duckingInfos an array of {@link DuckingInfo} objects for the
       *   audio zones where audio focus has changed.
       */
       oneway void onDevicesToDuckChange(in DuckingInfo[] duckingInfos);
}

Le informazioni pertinenti sul sistema audio sono contenute nelle informazioni sull'attenuazione audio:

parcelable DuckingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be ducked.
       */
       String[] deviceAddressesToDuck;
       /**
       *   List of addresses for audio output devices that were previously be
       *   ducked and should now be unducked.
       */
       String[] deviceAddressesToUnduck;
       /**
       *   List of usages currently holding focus for this audio zone.
       */
       String[] usagesHoldingFocus;
}

Oltre alle informazioni di configurazione dell'impianto audio dell'auto contenute negli indirizzi del dispositivo per l'attivazione/la disattivazione della funzionalità di attivazione audio, le informazioni sull'attivazione audio contengono anche informazioni su quali utilizzi degli attributi audio hanno il controllo. Lo scopo di questi dati è informare il sistema audio sugli utilizzi degli attributi audio attivi.

Questo è necessario perché, nella configurazione dell'impianto audio dell'auto, è possibile assegnare più attributi audio a un singolo dispositivo e, senza le informazioni aggiuntive, non è chiaro quali utilizzi sono attivi.

HAL 2.0 per il controllo audio AIDL

Per aggiornare le API e facilitare le nuove funzionalità, l'HAL di controllo audio AIDL è stata aggiornata alla versione 2.0 in Android 13:

  • Audio focus con PlaybackTrackMetadata
  • Callback per i guadagni audio

I metadati di riproduzione sono definiti in android.hardware.audio.common come segue:

parcelable PlaybackTrackMetadata {
       AudioUsage usage = INVALID;
       AudioContentType contentType = UNKNOWN;
       float gain;
       AudioChannelLayout channelMask;
       AudioDevice sourceDevice;
       String[] tags;
}

Tutte le altre funzionalità della versione 1.0 del controllo audio AIDL sono rimaste e possono essere utilizzate. Un'eccezione riguarda il metodo di modifica dell'attenzione audio, come descritto in On audio focus change method.

Mettere in primo piano il controllo audio con i metadati della traccia di riproduzione

Per esporre più informazioni al sistema audio sotto l'HAL, gli aggiornamenti ora espongono PlaybackTrackMetadata. Nello specifico, l'HAL di controllo audio è stato ampliato con un nuovo metodo:

interface IAudioControl {
       /**
       *   Notifies HAL of changes in audio focus status for focuses requested
       *   or abandoned by the HAL.
       *
       *   The HAL is not required to wait for a callback of AUDIOFOCUS_GAIN
       *   before playing audio, nor is it required to stop playing audio in the
       *   event of a AUDIOFOCUS_LOSS callback is received.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL is
       *    playing the stream in
       *   @param focusChange the AudioFocusChange that has occurred.
       */
       oneway void onAudioFocusChangeWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId,
       in AudioFocusChange focusChange);
}

Viene apportata una modifica simile e corrispondente a IFocusListener:

       /**
       *   Called to indicate that the audio output stream associated with
       *   {@link android.hardware.audio.common.PlaybackTrackMetadata} is
       *   abandoning focus as playback has stopped.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       */
       oneway void abandonAudioFocusWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId);
       /**
       *   Called to indicate that the audio output stream associated with
       *   {@link android.hardware.audio.common.PlaybackTrackMetadata} has taken
       *   the focus as playback is starting for the corresponding stream.
       *
       *   @param playbackMetaData The output stream metadata associated with
       *    the focus request
       *   @param zoneId The identifier for the audio zone that the HAL
       *    abandoning focus
       *   @param focusGain The focus type requested.
       */
       oneway void requestAudioFocusWithMetaData(
       in PlaybackTrackMetadata playbackMetaData, in int zoneId,
       in AudioFocusChange focusGain);
}

Sul metodo di modifica dell'audio

Le operazioni di messa a fuoco riportate sopra funzionano nello stesso modo di quelle descritte in Richiesta di messa a fuoco audio da HAL. Solo i metadati della traccia di riproduzione contengono più informazioni, oltre agli utilizzi degli attributi audio. In generale, a meno che non siano necessarie le informazioni aggiuntive fornite dai metadati dei canali di riproduzione, l'HAL di controllo Android aggiornato può continuare a utilizzare i metodi precedenti.

Se gli sviluppatori HAL decidono di non supportareIAudioControl#onAudioFocusChangeWithMetaData, il metodo deve restituire risultati con l'errore UNKNOWN_TRANSACTION come descritto in Utilizzare i metodi di interface con versione.

Il servizio audio chiama prima onAudioFocusChangeWithMetaData e poi riprova con il metodo onAudioFocusChange se si verifica un errore UNKNOWN_TRANSACTION.

Attivazione/disattivazione audio dell'auto con i metadati della traccia di riproduzione

La versione 2.0 dell'HAL di controllo audio AIDL ha aggiunto i metadati della traccia di riproduzione alle informazioni sull'attenuazione audio:

parcelable DuckingInfo {
       /**
       *   ID of the associated audio zone
       */
       int zoneId;
       /**
       *   List of addresses for audio output devices that should be ducked.
       */
       String[] deviceAddressesToDuck;
       /**
       *   List of addresses for audio output devices that were previously be
       *   ducked and should now be unducked.
       */
       String[] deviceAddressesToUnduck;
       /**
       *   List of usages currently holding focus for this audio zone.
       */
       String[] usagesHoldingFocus;
       /**
       *   List of output stream metadata associated with the current focus
       *   holder for this audio zone
       */
       @nullable PlaybackTrackMetadata[] playbackMetaDataHoldingFocus;
}

usagesHoldingFocus è deprecato. Ora gli sviluppatori devono utilizzare playbackMetaDataHoldingFocus per determinare l'utilizzo dell'attributo audio e altre informazioni sull'audio. Detto questo, il parametro usagesHoldingFocus contiene ancora le informazioni richieste fino a quando questa opzione non verrà formalmente rimossa.

Callback per il guadagno audio

Per rendere le modifiche audio al di sotto dell'HAL più visibili all'AAOS in Android 13, abbiamo aggiunto un meccanismo che puoi utilizzare per comunicare le modifiche dell'audio dall'impianto audio dell'auto al servizio audio dell'auto. Il meccanismo espone le variazioni dell'indice di volume del guadagno audio con il rispettivo motivo per cui è stato modificato il guadagno:

  • Restrizioni relative a contenuti bloccati o con audio disattivato
  • Limitazioni
  • Limitazioni di attenuazione

Queste modifiche espongono queste limitazioni al di sotto dell'HAL al servizio audio dell'auto e, infine, a un'app dell'interfaccia utente di sistema per informare l'utente. La seconda parte, l'esposizione a una possibile UI di sistema, è stata ulteriormente ampliata in Android 14 per consentire alle app UI di sistema di ottenere più facilmente queste informazioni tramite un meccanismo di callback delle informazioni sui gruppi di volumi.

L'API HAL di controllo audio registra il callback del guadagno come segue:

interface IAudioControl {
       /**
       *   Registers callback to be used by HAL for reporting unexpected gain(s)
       *    changed and the reason(s) why.
       *
       *   @param callback The {@link IAudioGainCallback}.
       */
       oneway void registerGainCallback(in IAudioGainCallback callback);
}

IAudioGainCallback è definito come segue:

interface IAudioGainCallback {
       /**
       *   Used to indicate that one or more audio device port gains have changed,
       *   i.e. initiated by HAL, not by CarAudioService.
       *   This is the counter part of the
       *   {@link onDevicesToDuckChange}, {@link onDevicesToMuteChange} and,
       *   {@link setAudioDeviceGainsChanged} APIs.
       *
       *   @param reasons List of reasons that triggered the given gains changed.
       *   @param gains List of gains affected by the change.
       */
       void onAudioDeviceGainsChanged(in Reasons[] reasons,
       in AudioGainConfigInfo[] gains);
}

Come evidenziato nella documentazione dell'API, il callback del guadagno viene registrato dal servizio audio dell'auto nell'HAL di controllo audio. Quando l'API viene chiamata dall'HAL di controllo audio, il servizio audio dell'auto risponde con un'azione corrispondente (ad esempio blocco, limite o attenuazione dell'indice di guadagno) .

L'HAL determina quando viene chiamata l'API, principalmente per segnalare le modifiche allo stato dell'indice di guadagno. In base ai requisiti normativi, l'impianto audio dell'auto deve eseguire l'azione richiesta e utilizzare il callout per segnalare informazioni al servizio audio dell'auto per consentire il consumo da parte dell'utente. Ad esempio, per mostrare un'interfaccia utente all'utente.

HAL 3.0 per il controllo audio AIDL

La versione HAL del controllo audio AIDL di Android 14 è stata aggiornata alla versione 3.0 per aggiornare le API in modo da fornire una funzionalità dell'indice di guadagno audio più solida. L'API HAL di controllo audio consente al servizio audio di impostare e annullare l'impostazione di un IModuleChangeCallback:

interface IAudioControl {
       /**
       *   Sets callback with HAL for notifying changes to hardware module
       *   (that is: {@link android.hardware.audio.core.IModule}) configurations.
       *
       *   @param callback The {@link IModuleChangeCallback} interface to use
       *    use when new updates are available for
       */
       void setModuleChangeCallback(in IModuleChangeCallback callback);
       /**
       *   Clears module change callback
       */
       void clearModuleChangeCallback();
}

Il codice setModuleChangeCallback viene registrato dal servizio audio per auto all'avvio del servizio o durante il recupero da un errore. Ad esempio, una notifica di morte del binder HAL di controllo audio ricevuta dal servizio audio dell'auto. L'implementazione dell'HAL di controllo audio deve sostituire qualsiasi callback di modifica del modulo esistente quando viene chiamata l'API.

Per l'API clearModuleChangeCallback, l'implementazione deve cancellare il callback esistente o non fare nulla se non esiste. È buona prassi per l'implementazione del controllo audio registrare un osservatore di interruzione per il callback e poi cancellare il callback se viene attivato l'evento on binder death.

IModuleChangeCallback è definito come segue:

oneway interface IModuleChangeCallback {
       /**
       *   Used to indicate that one or more {@link AudioPort} configs have
       *   changed. Implementations MUST return at least one AudioPort.
       *
       *   @param audioPorts list of {@link AudioPort} that are updated
       */
       void onAudioPortsChanged(in AudioPort[] audioPorts);
}

Quando il callback di modifica del modulo viene registrato dal servizio audio dell'auto, è pronto per ricevere le modifiche alle porte audio tramite l'API onAudioPortChanged. L'API può essere utilizzata per inizializzare i guadagni del volume per l'impianto audio non appena il callback è registrato. Per altre modifiche del guadagno dinamico, l'API può essere chiamata in qualsiasi momento. Le modifiche corrispondenti vengono applicate e il servizio audio dell'auto viene aggiornato di conseguenza.