HAL di controllo audio

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

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

La Figura 1 mostra una panoramica di alto livello 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 dell'audio nei casi d'uso automobilistici. Oltre agli effetti audio generici già forniti in Android, questo meccanismo consente alle app di sistema di impostare il bilanciamento e la dissolvenza dell'audio tramite le API CarAudioManager:

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, vengono chiamate le rispettive API HAL di controllo audio 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 in tutte le versioni dell'HAL di controllo audio, inclusa la nuova interfaccia HAL AIDL.

Richiesta di focus audio da HAL

AAOS, come Android, si basa sulla partecipazione attiva delle app alla messa a fuoco dell'audio per gestire la riproduzione audio nelle auto. Le informazioni sulla messa a fuoco vengono utilizzate per gestire i flussi da controllare per il volume e l'abbassamento. Pertanto, per ampliare ulteriormente la messa a fuoco dell'audio e per fornire 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 i suoni provenienti da fonti esterne ad Android per partecipare alle richieste di focus audio. Pertanto, è stata introdotta la versione 2 dell'HAL di controllo audio HIDL per consentire le 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 riportate sopra possono essere utilizzate per richiedere e abbandonare l'audio focus dall'HAL, rispettivamente. In risposta, il servizio audio dell'auto prende in considerazione la richiesta di focus audio e inoltra i risultati in modo asincrono al metodo IAudioControl#onAudioFocusChange.

Questa API può essere utilizzata anche per monitorare le modifiche alla richiesta di focus audio che ha origine dall'HAL di controllo audio. In generale, qualsiasi richiesta di messa a fuoco audio dall'HAL è considerata attiva, a differenza di una richiesta di messa a fuoco audio da Android, in cui solo la riproduzione di una traccia audio attiva corrispondente è considerata attiva.

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

Con l'avvento di AIDL e la migrazione richiesta in Android 12 (per saperne di più, vedi AIDL per HAL), l'HAL di controllo audio è stato migrato ad AIDL. Per le API HIDL audio control versione 2 esistenti, la migrazione richiedeva 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 dell'audio del gruppo di volumi

Android 12 ha introdotto la disattivazione dell'audio del gruppo di volumi 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 dell'audio intercettati dal servizio audio dell'auto.

Per attivare la funzionalità, gli OEM devono impostare la configurazione 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 una sovrapposizione di risorse di runtime per packages/services/Car/service/res/values/config.xml (per saperne di più, consulta Personalizzare la build con le sovrapposizioni di risorse). A partire da Android 13, puoi utilizzare le overlay delle risorse di runtime per modificare un valore di configurazione. Per saperne di più, consulta Modificare il valore delle risorse di un'app in fase di runtime.

Le app di sistema possono determinare se la funzionalità è abilitata utilizzando l'API CarAudioManager#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 dell'audio del gruppo di volumi:

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 sul silenziamento contengono le informazioni pertinenti sul silenziamento 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 l'audio KEYCODE_VOLUME_MUTE.

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

Quando è abilitato, entrambi i meccanismi attivano la disattivazione dell'audio nell'HAL di controllo audio.

Attenuazione automatica audio dell'auto

Android 12 ha introdotto la riduzione dell'audio dell'auto per ottimizzare il controllo della riproduzione simultanea dei flussi audio. Ciò consente agli OEM di implementare il proprio comportamento di ducking in base alla configurazione audio fisica di un'auto e allo stato di riproduzione attuale, come determinato dal servizio audio dell'auto.

Il meccanismo di abbassamento si basa sulle modifiche dello stack di messa a fuoco audio. Ogni volta che si verifica un cambio di messa a fuoco (richiesta di messa a fuoco o abbandono della messa a fuoco), viene informato l'HAL di controllo audio. Analogamente al supporto della disattivazione dell'audio del gruppo di volumi dell'auto, l'abbassamento dell'audio dell'auto può essere attivato 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'abbassamento dell'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'audio dell'auto contenute negli indirizzi del dispositivo per (non) abbassare il volume, le informazioni sull'abbassamento del volume contengono anche informazioni su quali usi degli attributi audio mantengono lo stato attivo. L'intenzione di questi dati è di informare il sistema audio su quali utilizzi degli attributi audio sono attivi.

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

HAL di controllo audio AIDL 2.0

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

  • Focus audio con PlaybackTrackMetadata
  • Callback dei 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 della messa a fuoco audio, come descritto in Sul metodo di modifica della messa a fuoco audio.

Focus sul 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);
}

Una modifica simile e corrispondente viene apportata 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 del focus audio

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

Se gli sviluppatori HAL decidono di non supportare IAudioControl#onAudioFocusChangeWithMetaData, il metodo deve restituire risultati con l'errore UNKNOWN_TRANSACTION come descritto in Utilizzo dei metodi dell'interfaccia con controllo delle versioni.

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

Abbassamento dell'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 di 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 degli attributi audio e altre informazioni audio. Detto questo, il parametro usagesHoldingFocus contiene ancora le informazioni richieste finché questa opzione non viene rimossa formalmente.

Callback del guadagno audio

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

  • Limitazioni per utenti bloccati o silenziati
  • Limitazioni
  • Limitazioni di attenuazione

Queste modifiche espongono queste limitazioni dal livello inferiore all'HAL al servizio audio dell'auto e, infine, a un'app UI 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 sul gruppo di volumi.

L'API HAL di controllo audio registra il callback del guadagno nel seguente modo:

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 blocca, limita o attenua l'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 di legge, il sistema audio dell'auto deve intraprendere l'azione richiesta e utilizzare il callback per comunicare le informazioni al servizio audio dell'auto per consentirne l'utilizzo da parte dell'utente. Ad esempio, per mostrare un'interfaccia utente all'utente.

HAL 3.0 per il controllo audio AIDL

La versione HAL di controllo audio AIDL di Android 14 è aggiornata alla versione 3.0 per aggiornare le API e fornire una funzionalità di indice di guadagno audio più solida. L'API HAL di controllo audio consente al servizio audio di impostare e annullare 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();
}

setModuleChangeCallback viene registrato dal servizio audio dell'auto all'avvio del servizio o durante il recupero da un errore. Ad esempio, una notifica di interruzione del binder HAL di controllo audio ricevuta dal servizio audio dell'auto. L'implementazione HAL del 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 ne esiste uno. È una buona pratica per l'implementazione del controllo audio registrare un osservatore di interruzione per il callback e quindi cancellare il callback se viene attivato 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 a ricevere modifiche alla porta audio tramite l'API onAudioPortChanged. L'API può essere utilizzata per inizializzare i guadagni di volume per il sistema audio non appena viene registrato il callback. Per altre modifiche del guadagno dinamico, l'API può essere chiamata in qualsiasi momento. Vengono applicate le modifiche corrispondenti e il servizio audio dell'auto viene aggiornato di conseguenza.