Como compartilhar entradas de áudio

A entrada de áudio geralmente vem do microfone integrado, de um microfone externo ou de uma interface de áudio conectada ao dispositivo. A entrada de áudio também pode vir de uma conversa telefônica.

Às vezes, dois ou mais apps podem querer "capturar" a mesma entrada de áudio. Eles podem estar realizando tarefas diferentes. Por exemplo, alguns apps que recebem áudio podem estar "gravando", como um gravador de voz simples, enquanto outros podem estar "ouvindo", como o Google Assistente ou um serviço de acessibilidade que responde a comandos de voz.

Em ambos os casos, esses apps querem receber entrada de áudio. Nesta página, usamos o termo "capturar" independentemente de um app estar gravando ou apenas ouvindo.

Se dois ou mais apps quiserem capturar áudio ao mesmo tempo, pode haver um problema na entrega do sinal de áudio da mesma fonte para todos eles. Esta página descreve como o sistema Android compartilha a entrada de áudio entre vários apps que capturam áudio.

Comportamento anterior ao Android 10

Antes do Android 10, o stream de áudio de entrada só podia ser capturado por um app por vez. Se algum app já estivesse gravando ou ouvindo áudio, seu app poderia criar um AudioRecord objeto, mas um erro seria retornado quando você chamasse AudioRecord.startRecording() e a gravação não seria iniciada.

Uma exceção a essa regra era quando um app privilegiado (como o Google Assistente ou um serviço de acessibilidade) tinha a permissão android.permission.CAPTURE_AUDIO_HOTWORD e usava uma fonte de áudio do tipo HOTWORD. Nesse caso, outro app poderia começar a gravar. Quando isso acontecia, o app privilegiado era encerrado e o novo app capturava a entrada.

Outra mudança foi adicionada no Android 9: apenas apps em execução em primeiro plano (ou um serviço em primeiro plano) podiam capturar a entrada de áudio. Quando um app sem um serviço em primeiro plano ou um componente de interface em primeiro plano começava a capturar, ele continuava em execução, mas recebia silêncio, mesmo que fosse o único app capturando áudio no momento.

Comportamento do Android 10

O comportamento anterior ao Android 10 é "por ordem de chegada". Depois que um app começa a capturar áudio, nenhum outro app pode acessar a entrada de áudio até que o app que está capturando áudio pare.

O Android 10 impõe um esquema de prioridade que pode alternar o stream de áudio de entrada entre apps enquanto eles estão em execução. Na maioria dos casos, se um novo app adquirir a entrada de áudio, o app que estava capturando anteriormente continuará em execução, mas receberá silêncio. Em alguns casos, o sistema pode continuar a transmitir áudio para os dois apps. Os vários cenários de compartilhamento são explicados abaixo.

Esse esquema é semelhante à maneira como a seleção de áudio processa vários apps que disputam o uso da saída de áudio. No entanto, a seleção de áudio é gerenciada por solicitações programáticas para ganhar e liberar a seleção, enquanto o esquema de troca de entrada descrito aqui é baseado em uma política de priorização que é aplicada automaticamente sempre que um novo app começa a capturar áudio.

Para fins de captura de áudio, o Android distingue dois tipos de apps:

  • Os apps "comuns" são instalados pelo usuário.
  • Os apps "privilegiados" vêm pré-instalados no dispositivo. Eles incluem o Google Assistente e todos os serviços de acessibilidade.

Além disso, um app é tratado de maneira diferente se usar uma fonte de áudio "sensível à privacidade": CAMCORDER ou VOICE_COMMUNICATION.

As regras de priorização para usar e compartilhar a entrada de áudio são as seguintes:

  • Os apps privilegiados têm maior prioridade do que os apps comuns.
  • Os apps com interfaces visíveis em primeiro plano têm maior prioridade do que os apps em segundo plano.
  • Os apps que capturam áudio de uma fonte sensível à privacidade têm maior prioridade do que os apps que não são.
  • Dois apps comuns nunca podem capturar áudio ao mesmo tempo.
  • Em algumas situações, um app privilegiado pode compartilhar a entrada de áudio com outro app.
  • Se dois apps em segundo plano da mesma prioridade estiverem capturando áudio, o último iniciado terá maior prioridade.

Cenários de compartilhamento

Quando dois apps estão tentando capturar áudio, os dois podem receber o sinal de entrada ou um deles pode receber silêncio.

Há quatro cenários principais:

  • Assistente + app comum
  • Serviço de acessibilidade + app comum
  • Dois apps comuns
  • Ligação + app comum

Assistente + app comum

O Assistente é um app privilegiado porque ele é pré-instalado e tem o papel RoleManager.ROLE_ASSISTANT. Qualquer outro app pré-instalado com esse papel é tratado de maneira semelhante.

O Android compartilha o áudio de entrada de acordo com estas regras:

  • O Assistente pode receber áudio (não importa se ele está em primeiro ou segundo plano), a menos que outro app que use uma fonte de áudio sensível à privacidade já esteja capturando.

  • O app recebe áudio, a menos que o Assistente tenha um componente de interface visível na parte de cima da tela.

Os dois apps só recebem áudio quando o Assistente está em segundo plano e o outro app não está capturando de uma fonte de áudio sensível à privacidade.

Serviço de acessibilidade + app comum

Um AccessibilityService requer uma declaração estrita declaration.

O Android compartilha o áudio de entrada de acordo com estas regras:

  • Se a interface do serviço estiver na parte de cima, o serviço e o app vão receber entrada de áudio. Esse comportamento oferece funcionalidades como controlar uma ligação ou captura de vídeo com comandos de voz.

  • Se o serviço não estiver na parte de cima, esse caso será tratado como o caso de dois apps comuns abaixo.

Dois apps comuns

Quando dois apps estão capturando simultaneamente, apenas um recebe áudio e o outro recebe silêncio.

O Android compartilha o áudio de entrada de acordo com estas regras:

  • Se nenhum dos apps for sensível à privacidade, o app com uma interface na parte de cima vai receber áudio. Se nenhum dos apps tiver uma interface, aquele que iniciou a captura mais recentemente vai receber áudio.
  • Se um dos apps for sensível à privacidade, ele vai receber áudio e o outro app vai receber silêncio, mesmo que tenha uma interface na parte de cima ou tenha começado a capturar mais recentemente.
  • Se os dois apps forem sensíveis à privacidade, o app que começou a capturar mais recentemente vai receber áudio e o outro vai receber silêncio.

Ligação + app comum

Uma ligação está ativa se o modo de áudio retornado por AudioManager.getMode() for MODE_IN_CALL ou MODE_IN_COMMUNICATION.

O Android compartilha o áudio de entrada de acordo com estas regras:

Comportamento do Android 11

O Android 11 (nível 30 da API) observa o esquema de prioridade do Android 10 descrito acima. Ele também oferece novos métodos em AudioRecord, MediaRecorder e AAudioStream que ativam e desativam a capacidade de capturar áudio simultaneamente, independentemente do caso de uso selecionado.

Os novos métodos são:

Quando setPrivacySensitive() é true, o caso de uso de captura é particular e nem mesmo um Assistente privilegiado pode gravar simultaneamente. Essa configuração substitui o comportamento padrão que depende da fonte de áudio. Por exemplo, VOICE_COMMUNICATION é particular por padrão, mas UNPROCESSED não é.

Alterações de configuração

Quando vários apps estão capturando áudio simultaneamente, apenas um ou dois deles estão "ativos" (recebendo áudio). Os outros estão silenciados (recebendo silêncio). Quando os apps ativos mudam, a estrutura de áudio pode reconfigurar os caminhos de áudio de acordo com estas regras:

  • O dispositivo de entrada de áudio de cada app ativo pode mudar (por exemplo, do microfone integrado para um fone de ouvido Bluetooth conectado).
  • O pré-processamento associado ao app ativo de maior prioridade é ativado. Todo o outro pré-processamento é ignorado.

Como um app ativo pode ser silenciado quando um app de maior prioridade se torna ativo, você pode registrar um AudioManager.AudioRecordingCallback no objeto AudioRecord ou MediaRecorder para ser notificado quando a configuração mudar. As possíveis mudanças podem ser:

  • Captura silenciada ou não silenciada
  • Dispositivo alterado
  • Pré-processamento alterado
  • Propriedades do stream alteradas (taxa de amostragem, máscara de canal, formato de amostra)

Você precisa chamar AudioRecord.registerAudioRecordingCallback() antes que a captura seja iniciada. O callback é executado apenas quando o app está recebendo áudio e ocorre uma mudança.

O método onRecordingConfigChanged() retorna uma AudioRecordingConfiguration que contém o estado atual de captura de áudio. Use os métodos a seguir para saber mais sobre a mudança:

isClientSilenced()
Retorna verdadeiro se o áudio retornado ao cliente estiver sendo silenciado devido à política de captura.
getAudioDevice()
Retorna o dispositivo de áudio ativo.
getEffects()
Retorna o efeito de pré-processamento ativo. O efeito ativo pode não ser o mesmo retornado por getClientEffects() se o cliente não for o app ativo de maior prioridade.
getFormat()
Retorna as propriedades do stream. Os dados de áudio reais recebidos pelo cliente sempre respeitam o formato necessário retornado por getClientFormat(). A estrutura realiza automaticamente a conversão de reamostragem, canal e formato necessários do formato usado na interface de hardware para o formato especificado pelo cliente.
AudioRecord.getActiveRecordingConfiguration().
Retorna a configuração de gravação ativa.

Você pode ter uma visão geral de todas as gravações ativas no dispositivo chamando AudioManager.getActiveRecordingConfigurations().