Foco de áudio

Antes de iniciar um fluxo lógico, um aplicativo deve solicitar foco de áudio usando os mesmos atributos de áudio que usará para seu fluxo lógico. Embora o envio de tal solicitação de foco seja recomendado, ele não é imposto pelo sistema. Alguns aplicativos podem ignorar explicitamente o envio da solicitação para alcançar comportamentos específicos (por exemplo, reproduzir som intencionalmente durante uma chamada telefônica).

Por esse motivo, você deve considerar o foco como uma forma de controlar e eliminar conflitos de reprodução indiretamente, e não como um mecanismo primário de controle de áudio; o veículo não deve depender do sistema de foco para operação do subsistema de áudio.

Interações de foco

Para atender às necessidades de AAOS, as solicitações de foco de áudio são tratadas com base em interações predefinidas entre o CarAudioContext da solicitação e os detentores de foco atuais. Existem três tipos de interações: exclusivas, rejeitadas e simultâneas.

Interação exclusiva

Em interações exclusivas, apenas um aplicativo pode manter o foco por vez. Portanto, a solicitação de foco recebida recebe o foco enquanto o detentor do foco existente perde o foco. Um exemplo disso seria quando um usuário inicia um novo aplicativo de música enquanto a música já está sendo reproduzida em um aplicativo existente. Como ambos estão reproduzindo mídia, apenas um dos aplicativos pode manter o foco por vez. Como resultado, a solicitação de foco do aplicativo recém-iniciado retornará com AUDIOFOCUS_REQUEST_GRANTED e o aplicativo que estiver tocando música receberá um evento de alteração de foco com um status de perda que corresponde ao tipo de solicitação que foi feita. Este é o modelo de interação mais comumente visto com o Android.

Rejeitar interação

Com interações de rejeição, a solicitação recebida é sempre rejeitada. Tentar tocar música enquanto uma chamada está em andamento é um exemplo de interação rejeitada. Nesse caso, se o discador estiver mantendo o foco de áudio para uma chamada e um segundo aplicativo solicitar o foco para reproduzir música, o aplicativo de música receberá AUDIOFOCUS_REQUEST_FAILED em resposta à sua solicitação. Como a solicitação de foco é rejeitada, nenhuma perda de foco de qualquer tipo é despachada para o detentor do foco atual.

Interação simultânea

O mais exclusivo do AAOS são as interações simultâneas. Isso dá aos aplicativos que solicitam foco de áudio no carro a capacidade de manter o foco simultaneamente com outros aplicativos. Para que uma interação simultânea ocorra, as seguintes condições devem ser atendidas. O:

Se esses critérios forem atendidos, a solicitação de foco retornará com AUDIOFOCUS_REQUEST_GRANTED enquanto o detentor do foco atual não terá alteração no foco. No entanto, se o detentor do foco atual optar por receber eventos de pato ou pausar quando abaixado, o detentor do foco atual perderá o foco da mesma forma que em uma interação exclusiva.

Como lidar com fluxos simultâneos

Embora a interação simultânea tenha muitos aplicativos úteis, os OEMs devem cuidar da mixagem e redução no nível do hardware nos dispositivos de saída. Por causa disso, é altamente recomendável que CarAudioContext s sejam roteados apenas para o mesmo dispositivo de saída que CarAudioContext s com o qual eles não podem tocar simultaneamente. Ao ter dispositivos de saída separados para fluxos simultâneos, isso permite que o HAL reduza um dos fluxos antes de misturá-los ou roteie os fluxos físicos para diferentes alto-falantes no veículo. Se os fluxos lógicos forem misturados no Android, seus ganhos serão inalterados e serão entregues como parte do mesmo fluxo físico.

Por exemplo, quando a navegação e a mídia são entregues simultaneamente, o ganho para o fluxo de mídia pode ser temporariamente reduzido (abaixado) para que as instruções de navegação possam ser ouvidas com mais clareza. Alternativamente, o fluxo de navegação pode ser roteado para os alto-falantes do lado do motorista enquanto a mídia continua a ser reproduzida pelo resto da cabine.

Matriz de interação

A tabela abaixo mostra a matriz de interação definida pelo CarAudioService . As linhas representam o CarAudioContext do detentor do foco atual e as colunas representam o da solicitação recebida.

Olhando para um exemplo, onde um aplicativo de mídia de música está atualmente mantendo o foco e um aplicativo de navegação solicita o foco, a matriz mostra que as duas interações podem ser reproduzidas simultaneamente, supondo que os outros critérios para interações simultâneas sejam atendidos.

Devido às interações simultâneas, é possível existir mais de um detentor de foco. Nesse caso, uma solicitação de foco recebida será comparada com cada um dos detentores de foco atuais antes de decidir que tipo de interação aplicar. Nesse caso, a interação mais conservadora vence (rejeitar, depois exclusiva e finalmente concorrente).

Na tabela a seguir, as interações de foco entre o CarAudioContext para uma solicitação de foco de entrada (colunas) e o contexto dos detentores de foco existentes (linhas) são fornecidas. Cada célula representa o tipo de interação esperado para os dois contextos, onde:

  • R: Rejeitar interação
  • E: Interação exclusiva
  • C: Interação simultânea

Interações de foco de áudio

Figura 1. Interações de foco de áudio

No Android 11, uma nova configuração de usuário foi introduzida para permitir que os usuários alterem o comportamento de interação entre navegação e chamadas telefônicas. Quando definido, android.car.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL alterará a interação entre as solicitações de foco NAVIGATION recebidas e os detentores de foco CALL atuais de concorrente para rejeitar . Portanto, se um usuário preferir que as instruções de navegação não interrompam sua chamada, ele poderá ativar essa configuração. Isso é persistido para o usuário e pode ser definido dinamicamente para que as solicitações de foco subsequentes respeitem o novo valor de configuração.

Foco de áudio atrasável

No Android 11, o AAOS adicionou suporte para solicitar foco de áudio adiado. Isso permite que solicitações de foco não transitórios sejam atrasadas quando sua interação com os detentores de foco atuais normalmente resultaria em sua rejeição. Uma vez que uma mudança no foco resulte em um estado em que a solicitação atrasada possa ganhar foco, a solicitação será concedida.

Regras para solicitações de foco de áudio atrasadas

  • Somente solicitações não transitórias - como mencionado anteriormente, uma solicitação atrasada só pode ser feita para fontes não transitórias. Isso é para evitar que um som transitório seja reproduzido muito depois de ser relevante.
  • Apenas uma solicitação pode ser atrasada por vez - Se uma solicitação adiada for feita enquanto já houver uma solicitação atrasada, a solicitação atrasada original receberá um evento de alteração AUDIOFOCUS_LOSS e a nova solicitação receberá uma resposta síncrona de AUDIOFOCUS_REQUEST_DELAYED .
  • As solicitações atrasáveis ​​devem ter um OnAudioFocusChangeListener . Uma vez que uma solicitação é atrasada, o listener será usado para notificar o solicitante quando a solicitação for concedida ( AUDIOFOCUS_GAIN ), ou se for rejeitada posteriormente ( AUDIOFOCUS_LOSS ).

Solicitar foco adiado

Para criar uma solicitação que pode ser atrasada, use AudioFocusRequest.Builder#setAcceptsDelayedFocusGain :

mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener();

mDelayedFocusRequest = new AudioFocusRequest
     .Builder(AudioManager.AUDIOFOCUS_GAIN)
     .setAudioAttributes(mMusicAudioAttrib)
     .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener)
     .setForceDucking(false)
     .setWillPauseWhenDucked(false)
     .setAcceptsDelayedFocusGain(true)
     .build();

Então, ao fazer a solicitação, trate da resposta AUDIOFOCUS_REQUEST_DELAYED :

int delayedFocusRequestResults = mAudioManager.requestAudioFocus(mDelayedFocusRequest);
if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// start audio playback
return;
}
if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
     // audio playback delayed to audio focus listener
     return;
}

Quando a solicitação é atrasada, o listener de foco é responsável por lidar com as alterações no foco:

private final class MediaWithDelayedFocusListener implements
OnAudioFocusChangeListener {
       @Override
       public void onAudioFocusChange(int focusChange) {
           synchronized (mLock) {
               switch (focusChange) {
                   case AudioManager.AUDIOFOCUS_GAIN:
                       … // Start focus playback
                   case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                       … // Pause media transiently
                   case AudioManager.AUDIOFOCUS_LOSS:
                       … // Stop media

Gerenciamento de foco multizona

Para veículos com várias zonas de áudio, o foco de áudio será gerenciado independentemente para cada zona. Como tal, uma solicitação para uma zona não levará em conta o que está mantendo o foco em outras zonas, nem fará com que os detentores de foco em outras zonas percam o foco. Com isso, o foco da cabine principal pode ser gerenciado separadamente de um sistema de entretenimento do banco traseiro, evitando a interrupção da reprodução de áudio em uma zona pelas mudanças de foco em outra.

Para todos os aplicativos, o gerenciamento de foco é feito pelo CarAudioService automaticamente. A zona de áudio de uma solicitação de foco é determinada com base em seu UserId ou UID associado. Para obter detalhes, consulte Roteamento de áudio .

Solicitando áudio de várias zonas simultaneamente

Se um aplicativo quiser reproduzir áudio em várias zonas simultaneamente, ele deverá solicitar o foco para cada zona incluindo AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID no pacote:

//Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
Bundle bundle = new Bundle();
bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID,
               zoneId);

AudioAttributes attributesWithZone = new AudioAttributes.Builder()
     .setUsage(AudioAttributes.USAGE_MEDIA)
     .addBundle(bundle)
     .build();

//Create focus request using built attributesWithZone

Esse parâmetro de pacote permite que o solicitante substitua os mapeamentos automáticos de zona de áudio para usar o ID de zona especificado. Portanto, com isso, um aplicativo pode emitir solicitações separadas para diferentes zonas de áudio.

Foco de áudio HAL

A partir do Android 11, a HAL agora está habilitada para solicitar o foco em nome de streams externos. Embora opcionais, essas APIs são altamente recomendadas para permitir que sons externos sejam melhores participantes do ecossistema Android e forneçam uma experiência de usuário mais suave.

Tenha em mente que o HAL ainda é responsável por fazer a decisão final sobre quais sons devem ter prioridade. Nessa medida, sons críticos de emergência e segurança devem ser reproduzidos independentemente de o HAL receber ou não o foco de áudio e devem continuar a ser reproduzidos conforme apropriado, mesmo que o HAL perca o foco de áudio. O mesmo vale para quaisquer sons exigidos pelos regulamentos.

Na mesma linha, o HAL ainda deve silenciar proativamente os fluxos do Android conforme apropriado ao reproduzir sons críticos de emergência ou segurança para garantir que sejam ouvidos com clareza.

AudioControl@2.0

A versão 2.0 do AudioControl HAL apresenta várias novas APIs:

API Propósito
IAudioControl#registerFocusListener Registra uma instância de IFocusListener com o AudioControl HAL. Este ouvinte permite que o HAL solicite e abandone o foco de áudio. Espera-se que o HAl forneça uma instância ICloseHandle a ser usada pelo Android para cancelar o registro do ouvinte.
IAudioControl#onAudioFocusChange Notifica o HAL sobre alterações no status para focar solicitações feitas pelo HAL por meio do IFocusListener . Isso inclui respostas a solicitações de foco inicial.
IFocusListener#requestAudioFocus As solicitações se concentram em nome da HAL para um uso especificado, ID de zona e tipo de ganho de foco.
IFocusListener#abandonAudioFocus Abandona as solicitações de foco HAL existentes para o uso e o ID de zona especificados.

A HAL pode ter várias solicitações de foco ao mesmo tempo, mas está limitada a uma solicitação por uso e emparelhamento de ID de zona. Observe que o Android assume que o HAL começará imediatamente a reproduzir sons para um uso assim que uma solicitação for feita e continuará a fazê-lo até abandonar o foco.

Além de registerFocusListener , essas solicitações são todas oneway para garantir que o Android não atrase o HAL enquanto uma solicitação de foco é processada. O HAL não deve esperar para ganhar foco antes de reproduzir sons críticos de segurança. É opcional para o HAL ouvir e responder a mudanças no foco de áudio por meio IAudioControl#onAudioFocusChange , embora seja recomendado quando apropriado.