O AAOS tem o próprio gerenciamento de volume no CarAudioService
. Ele usa volumes
fixos com a expectativa de que os volumes sejam aplicados abaixo do HAL por um amplificador
de hardware, em vez de no software. Ele também organiza os dispositivos de saída em grupos de volume
para aplicar os mesmos ganhos a todos os dispositivos associados ao grupo de volume.
Usar volumes fixos
As implementações do AAOS precisam controlar o volume usando um amplificador de hardware em vez de um
misturador de software. Para evitar efeitos colaterais, defina a flag config_useFixedVolume
como verdadeira (sobreposição conforme necessário):
<resources> <!-- Car uses hardware amplifier for volume. --> <bool name="config_useFixedVolume">true</bool> </resources>
Quando a flag config_useFixedVolume
não está definida (ou definida como falsa),
os aplicativos podem chamar AudioManager.setStreamVolume()
e mudar o
volume por tipo de stream no mixer de software. Isso pode ser indesejável devido
ao possível efeito em outros aplicativos e ao fato de que a atenuação de volume no
misturador de software resulta em menos bits significativos disponíveis no sinal quando
recebido no amplificador de hardware.
Grupos de volumes
Os grupos de volume gerenciam os volumes de uma coleção de dispositivos em uma zona de áudio. Para cada grupo de volume, o volume pode ser controlado de forma independente, e os ganhos resultantes são configurados nos dispositivos associados para serem aplicados pelo amplificador do veículo. As configurações de volume são mantidas para o usuário e carregadas quando ele faz login.
Como definir grupos de volume
O CarAudioService usa grupos de volume definidos em car_audio_configuration.xml
:
<audioZoneConfiguration version="2.0"> <zones> <zone name="primary zone" isPrimary="true"> <volumeGroups> <group> <device address="bus0_media_out"> <context context="music"/> </device> </group> <group> <device address="bus1_navigation_out"> <context context="navigation"/> </device> <device address="bus2_voice_command_out"> <context context="voice_command"/> </device> </group> ... </volumeGroups> </zone> </zones> </audioZoneConfiguration>
Exemplo de implementação de car_audio_configuration.xml
.
Cada grupo de volume precisa conter um ou mais dispositivos de saída com endereços associados.
Esses endereços precisam corresponder aos dispositivos de saída definidos em
audio_policy_configuration.xml
.
Como configurar ganhos de grupos de volume
Cada grupo de volume tem valores de ganho mínimo, máximo e padrão, além de
um tamanho de etapa. Eles são determinados com base nos valores configurados em
audio_policy_configuration.xml
para os dispositivos associados
ao grupo de volume.
<devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS" address="bus0_media_out"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> <gains> <gain name="" mode="AUDIO_GAIN_MODE_JOINT" minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/> </gains> </devicePort>
Durante a inicialização, o grupo de volume vai verificar os valores de ganho dos dispositivos associados e configurar o grupo da seguinte maneira:
- Tamanho do passo. Precisa ser o mesmo para todos os dispositivos controlados pelo grupo de volume
- Ganho mínimo. Menor ganho mínimo entre os dispositivos no grupo
- Ganho máximo. Ganho máximo mais alto entre os dispositivos do grupo
- Ganho padrão. Ganho padrão mais alto entre os dispositivos do grupo
Devido à forma como esses valores são configurados, é possível definir o ganho de um grupo de volume fora do intervalo compatível com um dispositivo associado ao grupo de volume. Nesse caso, o ganho será definido como o valor mínimo ou máximo do dispositivo com base no valor do grupo de volume abaixo ou acima do intervalo.
Identificadores de grupos de volumes
Os grupos de volume são identificados no momento da execução pela ordem de definição no arquivo XML.
Os IDs variam de 0 a N-1 em uma zona de áudio, em que N é o número de grupos de volume nessa zona. Dessa forma, os IDs de grupos de volumes não são exclusivos entre as zonas. Esses identificadores
são usados para APIs CarAudioManager
associadas a grupos de volume. Qualquer API
que receba uma groupId
sem uma zoneId
vai usar a
zona de áudio principal por padrão.
Gerenciamento de volume de várias zonas
Cada zona de áudio precisa ter um ou mais grupos de volume, e cada grupo de volume
é associado a uma única zona de áudio. Essa relação é definida como parte de
car_audio_configuration.xml
. Consulte o exemplo fornecido em
Como definir grupos de volumes acima.
Os níveis de volume atuais de cada zona são mantidos para o usuário associado a essa zona. Essas configurações são específicas da zona, ou seja, se um usuário fizer login em uma tela associada à zona principal e depois fizer login em uma zona associada a uma zona de áudio secundária, os níveis de volume carregados e mantidos para a primeira zona serão diferentes dos da zona secundária.
Como processar eventos de teclas de volume
O Android define vários keycodes para controle de volume, incluindo
KEYCODE_VOLUME_UP
, KEYCODE_VOLUME_DOWN
e
KEYCODE_VOLUME_MUTE
. Por padrão, o Android encaminha os eventos da tecla de volume
para os aplicativos. As implementações automotivas precisam forçar esses eventos principais para
CarAudioService
, que pode chamar setGroupVolume
ou
setMasterMute
conforme apropriado.
Para forçar esse comportamento, defina a flag config_handleVolumeKeysInWindowManager
como true
:
<resources> <bool name="config_handleVolumeKeysInWindowManager">true</bool> </resources>
No momento, os eventos de tecla de volume não têm como distinguir para qual zona eles se destinam
e, portanto, são considerados associados à zona de áudio principal.
Quando um evento de tecla de volume é recebido, CarAudioService
determina qual grupo
de volume ajustar, recuperando os contextos de áudio dos players ativos e ajustando
o grupo de volume que contém o dispositivo de saída associado ao contexto de áudio de maior prioridade. A priorização é determinada com base em uma ordem fixa definida em
CarVolume.AUDIO_CONTEXT_VOLUME_PRIORITY
.
Desvanecimento e equilíbrio
As duas versões da HAL AudioControl incluem APIs para definir o fade e o equilíbrio no
veículo. Há APIs do sistema correspondentes para o CarAudioManager que transmitem valores
para a HAL AudioControl. Essas APIs exigem
android.car.permission.CAR_CONTROL_AUDIO_VOLUME
.
As APIs AudioControl são:
setBalanceTowardRight(float value)
: muda o volume do alto-falante para o lado direito (+) ou esquerdo (-) do carro. 0,0 é centralizado, +1,0 é totalmente à direita, -1,0 é totalmente à esquerda, e um valor fora do intervalo -1 a 1 é um erro.setFadeTowardFront(float value)
: muda o volume do alto-falante para a parte da frente (+) ou de trás (-) do carro. 0,0 é centralizado, +1,0 é totalmente para frente, -1,0 é totalmente para trás, e um valor fora do intervalo -1 a 1 é um erro.
Cabe aos OEMs decidir como esses valores serão aplicados e como vão ser mostrados aos usuários. Eles podem ser aplicados apenas a mídia ou em todo o sistema para todos os sons do Android.
O Android 11 também introduziu suporte para a aplicação de efeitos de áudio em dispositivos de saída. Com isso, é possível gerenciar o desbotamento e o equilíbrio usando efeitos de áudio nos dispositivos de saída apropriados, em vez de usar essas APIs.
Redução de áudio
A redução de áudio ocorre quando o veículo reduz o ganho de um stream para que outro stream tocado ao mesmo tempo possa ser ouvido com mais clareza. No AAOS, a redução de áudio é deixada para a HAL implementar, já que há muitos sons fora do Android que o SO não controla. No Android 11, a principal informação disponível para a HAL para tomar decisões de inserção é se dois dispositivos de saída têm streams ativos.
Quando se abaixar
Embora seja responsabilidade do OEM individual determinar como o ducking será processado pelo HAL, recomendamos algumas diretrizes gerais. Vários streams reproduzidos no Android geralmente ocorrem quando dois apps/serviços mantêm o foco de áudio simultaneamente. Com isso em mente, consulte a Matriz de interação para saber quando o Android pode conceder foco simultâneo e, portanto, quando é possível que duas transmissões diferentes sejam reproduzidas ao mesmo tempo.
Lembre-se de que todos os streams misturados pelo Android serão feitos antes de qualquer ganho ser aplicado. Portanto, qualquer transmissão que precise ser reduzida quando reproduzida simultaneamente com outra precisa ser roteada para dispositivos de saída separados para que o HAL possa aplicar a redução antes de misturá-las.
Comportamento de abatimento recomendado
Confira a seguir possíveis interações simultâneas em que recomendamos a ocultação de elementos:
EMERGENCY
. Diminua ou desative o som de tudo, excetoSAFETY
, para garantir que o motorista ouça o som.SAFETY
. Ocultar tudo, excetoEMERGENCY
, para garantir que o motorista ouça o somNAVIGATION
. Ocultar tudo, excetoSAFETY
eEMERGENCY
CALL
. Ocultar tudo, excetoSAFETY
,EMERGENCY
eNAVIGATION
VOICE
. PatoCALL_RING
- Cabe aos OEMs determinar a importância do
VEHICLE_SOUNDS
ativo e se eles precisam ou não silenciar outros sons para garantir que o motorista os ouça. MUSIC
eANNOUNCEMENT
precisam ser evitados por tudo. A principal exceção a isso são os tons de interação por toque, que atualmente são reproduzidos comoSYSTEM_SOUND
Outras considerações ao usar o recurso de abatimento
Alguns apps/serviços, como navegação ou assistente, podem usar vários players para concluir as ações. Os OEMs precisam evitar o desbloqueio muito agressivo com base no momento em que os dados de streaming param de chegar por esses dispositivos de saída para garantir que o usuário não tenha um retorno momentâneo da mídia para o volume máximo antes de ser reduzido novamente quando a próxima reprodução do app de navegação ou assistente começar.
Para veículos com vários estágios de som com isolamento suficiente, também há a opção de encaminhar o áudio para diferentes áreas do carro em vez de abaixá-lo. Por exemplo, as instruções de navegação podem ser encaminhadas para os alto-falantes do encosto de cabeça do motorista enquanto a música continua tocando em todo o carro com um volume normal.
Sons de segurança essenciais
Embora o Android 11 tenha introduzido
APIs de foco de áudio HAL,
ainda é responsabilidade da HAL garantir que os sons essenciais de segurança sejam priorizados em
relação a outros. Mesmo que o HAL mantenha o foco de áudio para USAGE_EMERGENCY
, isso não
garante que apps e serviços no Android não vão tocar sons. Cabe ao HAL
determinar quais streams do Android precisam ser misturados ou silenciados quando os sons de segurança críticos são
reproduzidos.
Como configurar a interface de configurações de volume
O AAOS separa a interface de configurações de volume da configuração do grupo de volume, que pode ser sobreposta, conforme descrito em Como configurar grupos de volume. Essa separação garante que nenhuma mudança seja necessária se a configuração dos grupos de volume mudar no futuro.
Na interface de configurações do carro, o arquivo packages/apps/Car/Settings/res/xml/car_volume_items.xml
contém elementos de interface (título e recursos de ícone) associados a cada
AudioAttributes.USAGE
definido. Esse arquivo fornece uma renderização razoável do
VolumeGroups
definido usando recursos associados ao primeiro
uso reconhecido contido em cada VolumeGroup.
Por exemplo, o exemplo a seguir define um VolumeGroup como incluindo
voice_communication
e voice_communication_signalling
. A implementação
padrão da interface de configurações do carro renderiza o VolumeGroup usando os recursos associados
a voice_communication
, que é o primeiro no arquivo.
<carVolumeItems xmlns:car="http://schemas.android.com/apk/res-auto"> <item car:usage="voice_communication" car:title="@*android:string/volume_call" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="voice_communication_signalling" car:title="@*android:string/volume_call" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="media" car:title="@*android:string/volume_music" car:icon="@*android:drawable/ic_audio_media"/> <item car:usage="game" car:title="@*android:string/volume_music" car:icon="@*android:drawable/ic_audio_media"/> <item car:usage="alarm" car:title="@*android:string/volume_alarm" car:icon="@*android:drawable/ic_audio_alarm"/> <item car:usage="assistance_navigation_guidance" car:title="@string/navi_volume_title" car:icon="@drawable/ic_audio_navi"/> <item car:usage="notification_ringtone" car:title="@*android:string/volume_ringtone" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="assistant" car:title="@*android:string/volume_unknown" car:icon="@*android:drawable/ic_audio_vol"/> <item car:usage="notification" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_communication_request" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_communication_instant" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_communication_delayed" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="notification_event" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="assistance_accessibility" car:title="@*android:string/volume_notification" car:icon="@*android:drawable/ic_audio_ring_notif"/> <item car:usage="assistance_sonification" car:title="@*android:string/volume_unknown" car:icon="@*android:drawable/ic_audio_vol"/> <item car:usage="unknown" car:title="@*android:string/volume_unknown" car:icon="@*android:drawable/ic_audio_vol"/> </carVolumeItems>
Os atributos e valores usados na configuração acima são declarados em
packages/apps/Car/Settings/res/values/attrs.xml
. A interface de configurações
de volume usa as seguintes APIs do CarAudioManager baseadas em VolumeGroup:
getVolumeGroupCount()
para saber quantos controles precisam ser desenhados.getGroupMinVolume()
egetGroupMaxVolume()
para receber os limites inferior e superior.getGroupVolume()
para saber o volume atual.registerVolumeChangeObserver()
para receber notificações sobre mudanças no volume.