Gerenciamento de volume

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, exceto SAFETY, para garantir que o motorista ouça o som.
  • SAFETY. Ocultar tudo, exceto EMERGENCY, para garantir que o motorista ouça o som
  • NAVIGATION. Ocultar tudo, exceto SAFETY e EMERGENCY
  • CALL. Ocultar tudo, exceto SAFETY, EMERGENCY e NAVIGATION
  • VOICE. Pato CALL_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 e ANNOUNCEMENT 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 como SYSTEM_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() e getGroupMaxVolume() para receber os limites inferior e superior.
  • getGroupVolume() para saber o volume atual.
  • registerVolumeChangeObserver() para receber notificações sobre mudanças no volume.