HAL de controle de áudio

A HAL de controle de áudio foi introduzida no Android 9 para oferecer suporte a casos de uso de áudio relevantes para o setor automotivo. A partir do Android 14, a HAL de controle de áudio oferece suporte a:

  • Esmaecer e equilibrar
  • Solicitação de seleção de áudio da HAL
  • Desativar som e diminuir volume do dispositivo
  • Mudanças no ganho do dispositivo de áudio
  • Mudanças na configuração da porta de áudio

A figura 1 mostra uma visão geral da arquitetura do serviço de áudio do carro em com as quais o serviço de áudio do carro se comunica com a HAL de controle de áudio.

Configurar áudio em várias zonas

Figura 1. Configurar áudio em várias zonas.

Esmaecer e balancear o áudio

A HAL de controle de áudio HIDL versão 1 foi lançada no Android 9 para oferecer suporte à esmaecimento e equilíbrio do áudio no uso automotivo casos de uso diferentes. Separado dos efeitos de áudio genéricos já fornecidos no Android, este permite que apps do sistema definam o equilíbrio de áudio e esmaeçam APIs do 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);
}

Depois que essas APIs são chamadas, as respectivas APIs HAL de controle de áudio são chamadas do serviço de áudio do carro:

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

A API está disponível em todas as versões da HAL de controle de áudio, incluindo interface HAL da AIDL.

Solicitação de seleção de áudio da HAL

Assim como o Android, o AAOS depende da participação ativa de apps no áudio para gerenciar a reprodução de áudio em carros. As informações de foco são usadas para gerenciar quais transmissões controlar o volume e a redução de volume. Assim, para nos aprofundarmos mais a seleção de áudio e fornecer uma melhor integração de sons específicos de carros ao a experiência Android, os seguintes atributos de áudio foram introduzidos no Android 11:

  • EMERGENCY
  • SAFETY
  • VEHICLE_STATUS
  • ANNOUNCEMENT

Além dessa mudança, um mecanismo foi adicionado para sons originados fora do Android para participar de solicitações de seleção de áudio. Assim, o áudio HIDL A versão 2 da HAL de controle foi introduzida para permitir solicitações de foco originadas de fora do 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);
}

Em que IFocusListener é definido como:

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

As APIs acima podem ser usadas para solicitar e abandonar a seleção de áudio da HAL, respectivamente. Em resposta, o serviço de áudio do carro considera a seleção de áudio e encaminha os resultados de maneira assíncrona à IAudioControl#onAudioFocusChange.

Essa API também pode ser usada para monitorar alterações da solicitação de seleção de áudio que tem origem na HAL de controle de áudio. Em geral, a seleção de áudio em pé solicitação da HAL é considerada ativa, o que é diferente de uma seleção de áudio do Android, em que apenas uma reprodução de faixa de áudio ativa correspondente é considerado ativo.

Migrar o HIDL para a HAL de controle de áudio AIDL

Com o advento da AIDL e a migração necessária no Android 12 (para saber mais, consulte AIDL para HALs), a HAL de controle de áudio era migrados para a AIDL. Para as APIs de controle de áudio HIDL da versão 2, a migração exigiam pequenas atualizações para os métodos existentes:

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 o IFocusListener correspondente:

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

Som do grupo de volumes desativado

O Android 12 introduziu o silenciamento de grupos de volumes para permitir um controle de silenciamento mais abrangente durante as interações de áudio do usuário. Isso permite que a HAL de controle de áudio receba eventos de silenciamento quando interceptados pelo carro. serviço de áudio.

Para ativar o recurso, os OEMs precisam definir a configuração audioUseCarVolumeGroupMuting para true no serviço de carro 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>

Antes do Android 13, a configuração precisava ser substituída com uma sobreposição de recursos no ambiente de execução packages/services/Car/service/res/values/config.xml (para saber mais, consulte Personalizar a versão com recursos sobreposições). No Android 13, é possível usar sobreposições de recursos no ambiente de execução para alterar o valor da configuração. Para saber mais, consulte Mudar o valor dos recursos de um app durante a execução.

Os aplicativos do sistema podem determinar se o recurso foi ativado usando o API CarAudioManager#isAudioFeatureEnabled. O parâmetro passado deve ser o CarAudioManager.AUDIO_FEATURE_VOLUME_GROUP_MUTING. O método retorna true se o recurso estiver ativado no dispositivo. Caso contrário, será false.

Além de ativar o recurso audioUseCarVolumeGroupMuting, a AIDL A HAL de controle de áudio precisa implementar o mecanismo de silenciamento do grupo de volume:

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

Quando as informações sobre silenciamento contiverem as informações pertinentes sobre como desativar o som do sistema de áudio:

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

O AAOS tem dois mecanismos diferentes para silenciar, com base nos seguintes fatores:

  • Eventos principais que usam o áudio KEYCODE_VOLUME_MUTE (link em inglês).

  • Chamadas diretas para o serviço de áudio do carro usando a API de silenciamento do gerenciador de áudio do carro CarAudioManager#setVolumeGroupMute:

Quando ativados, os dois mecanismos acionam o silenciamento de chamadas para a HAL de controle de áudio.

Redução de áudio do carro

O Android 12 introduziu a redução de áudio do carro para otimizar o controle de transmissão simultânea. a reprodução de streams de áudio. Isso permite que OEMs implementem a própria redução de volume comportamento com base na configuração de áudio física do carro e na reprodução atual estado, conforme determinado pelo serviço de áudio do carro.

O mecanismo de redução é baseado nas mudanças da pilha de foco de áudio. Sempre que um mudança de foco (seja uma solicitação ou um abandono de foco), o áudio de controle HAL é informada. Semelhante ao suporte para desativar o som do grupo de volumes de carro, A redução de áudio pode ser ativada com a flag de configuração 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>

Para ativar o recurso, a HAL de controle de áudio AIDL precisa implementar as lógica com o sinal recebido do serviço de áudio do carro:

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

As informações relevantes do sistema de áudio estão contidas na redução de áudio informações:

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

Além das informações de configuração de áudio do carro contidas nos endereços do dispositivo para se abaixar, as informações de redução também contêm informações sobre qual áudio de uso de atributos estão mantendo o foco. A intenção desses dados é informar sistema de áudio em que os usos de atributos de áudio estão ativos.

Isso é necessário porque, na configuração de áudio do carro, vários tipos de áudio atributos podem ser atribuídos a um único dispositivo e, sem os extras não está claro quais usos estão ativos.

HAL 2.0 de controle de áudio AIDL

Para atualizar APIs e facilitar novas funcionalidades, a HAL de controle de áudio AIDL foi atualizada para a versão 2.0 no Android 13:

  • Seleção de áudio com PlaybackTrackMetadata
  • O áudio recebe uma chamada de retorno

Os metadados de reprodução são definidos em android.hardware.audio.common da seguinte maneira:

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

Todas as outras funcionalidades do controle de áudio AIDL versão 1.0 foram mantidas e podem ser usados. Uma exceção diz respeito ao método de alteração da seleção de áudio, conforme descrito em No método de mudança de seleção de áudio.

Foco do controle de áudio com metadados da faixa de reprodução

Para expor mais informações ao sistema de áudio abaixo da HAL, as atualizações agora expõem PlaybackTrackMetadata: Especificamente, a HAL de controle de áudio foi expandida com um novo método:

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

Uma mudança semelhante e correspondente é feita em 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);
}

Método de mudança na seleção de áudio

As operações de seleção acima têm o mesmo desempenho que as descritas em Áudio solicitação de foco da HAL. Somente os metadados da faixa de reprodução e os usos de atributos de áudio. Em geral, a menos que o código informações fornecidas pelos metadados da faixa de reprodução são necessárias, o Android e a HAL de controle podem continuar a usar os métodos anteriores.

Se os desenvolvedores de HAL decidirem não oferecer suporte IAudioControl#onAudioFocusChangeWithMetaData, o método retornará resultados. com o erro UNKNOWN_TRANSACTION, conforme descrito em Como usar a interface com controle de versão Métodos.

O serviço de áudio chama primeiro onAudioFocusChangeWithMetaData e Em seguida, tenta novamente com o método onAudioFocusChange se um UNKNOWN_TRANSACTION os resultados da falha.

Redução de áudio do carro com metadados da faixa de reprodução

A versão 2.0 da HAL de controle de áudio AIDL adicionou os metadados da faixa de reprodução ao as informações de redução de áudio:

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

O uso de usagesHoldingFocus foi descontinuado. Agora, os desenvolvedores devem usar playbackMetaDataHoldingFocus para determinar o uso do atributo de áudio e outros informações de áudio. Dito isso, o parâmetro usagesHoldingFocus ainda contém as informações necessárias até que a opção seja removida formalmente.

Callback de ganho de áudio

Para fazer com que as mudanças de áudio abaixo da HAL fiquem mais visíveis para o AAOS no Android 13, adicionamos um mecanismo que pode ser usado para comunicar mudanças de áudio do sistema de áudio do carro para o serviço de áudio do carro. A o mecanismo expõe alterações no índice de volume de ganho de áudio com o respectivo motivo o ganho foi alterado:

  • Restrições bloqueadas ou silenciadas
  • Restrições de limitações
  • Restrições de atenuação

Essas alterações expõem as restrições abaixo da HAL para a serviço de áudio do carro e, por fim, para um app de interface do sistema para informar o usuário. A última parte, a exposição a uma possível interface do sistema, foi expandida ainda mais Android 14 para permitir que apps de interface do sistema recebam essas informações mais rapidamente usando um mecanismo de callback de informações do grupo de volumes.

A API HAL de controle de áudio registra o callback de ganho da seguinte forma:

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

O IAudioGainCallback é definido da seguinte maneira:

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

Conforme destacado na documentação da API, o retorno de chamada de ganho é registrado pelo para a HAL de controle de áudio. Quando a API é chamada no HAL de controle de áudio, o serviço de áudio do carro responde com uma ação correspondente (como bloquear, limitar ou atenuar o índice de ganho) .

A HAL determina quando a API é chamada, principalmente para relatar alterações na obter o status do índice. Para atender aos requisitos regulatórios, o sistema de áudio do carro deve realizar a ação necessária e usar o callback para relatar informações ao o serviço de áudio do carro para permitir o consumo dos usuários. Por exemplo, para mostrar uma interface para o usuário.

HAL 3.0 de controle de áudio AIDL

A versão da HAL de controle de áudio AIDL do Android 14 é atualizado para a versão 3.0 para atualizar as APIs e oferecer ganho de áudio mais robusto. a funcionalidade do índice. A API de controle de áudio HAL permite que o serviço de áudio definir e cancelar a definição de uma 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();
}

O setModuleChangeCallback é registrado pelo serviço de áudio do carro quando o serviço é iniciado ou durante a recuperação de um erro. Por exemplo, um controle de áudio Notificação de morte da vinculação da HAL recebida pelo serviço de áudio do carro. O áudio a implementação de HAL de controle deve substituir qualquer callback de alteração de módulo existente. quando a API é chamada.

Para a API clearModuleChangeCallback, a implementação precisa limpar o callback existente ou não fazer nada se não existir um. É uma boa prática a implementação de controle de áudio para registrar um observador de morte para o callback e limpar o callback se o encerramento do binder for acionado.

IModuleChangeCallback é definido da seguinte maneira:

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 o callback de alteração do módulo é registrado pelo serviço de áudio do carro, pronto para receber mudanças de porta de áudio pela API onAudioPortChanged. A pode ser usada para inicializar ganhos de volume para o sistema de áudio assim que o é registrado. Para outras mudanças dinâmicas de ganho, a API pode ser chamada a qualquer momento. As mudanças correspondentes serão aplicadas, e o serviço de áudio do carro será atualizado de acordo.