Como compartilhar entradas de áudio

A entrada de áudio normalmente é proveniente de um microfone integrado, externo ou de uma interface de áudio anexada ao dispositivo. A entrada também pode vir de uma conversa telefônica.

Às vezes, dois ou mais aplicativos podem querer "capturar" a mesma entrada de áudio. Eles podem estar executando tarefas diferentes. Por exemplo, alguns aplicativos que recebem o á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 responda a comandos de voz.

De qualquer forma, os aplicativos querem receber a entrada de áudio. No decorrer desta página, usamos o termo "capturar" independentemente do fato de um aplicativo estar gravando ou só ouvindo.

Se dois ou mais aplicativos quiserem capturar o áudio ao mesmo tempo, poderá 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 entre vários aplicativos que fazem a captura do áudio.

Comportamento pré-Android 10

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

Uma exceção a essa regra era quando um aplicativo 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 aplicativo poderia começar a gravar. Quando isso acontecia, o aplicativo privilegiado era encerrado e o novo aplicativo capturava a entrada.

Mais uma mudança foi adicionada no Android 9: somente aplicativos que operam em primeiro plano (ou um serviço em primeiro plano) poderiam capturar a entrada de áudio. Quando um aplicativo sem componente de IU ou serviço em primeiro plano iniciava a captura, o aplicativo continuava a operar, mas recebia silêncio, mesmo que fosse o único a capturar áudio no momento.

Novo comportamento

O comportamento anterior era "o primeiro a chegar é o primeiro a receber". Uma vez que um aplicativo começasse a capturar o áudio, todos os outros aplicativos não tinham como acessar a entrada até que esse processo de captura fosse interrompido.

O Android 10 (nível de API 29) e versões superiores impõe um esquema de prioridade que pode trocar o stream do áudio de entrada entre aplicativos em execução. Na maioria dos casos, se um novo aplicativo acessar a entrada de áudio, o que estava fazendo a captura continuará a operar, mas receberá silêncio. Em alguns casos, o sistema pode continuar a entregar o áudio aos dois aplicativos. Os diversos cenários de compartilhamento são explicados abaixo.

Este esquema é semelhante à forma com que a seleção de áudio processa vários aplicativos 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 foco. Já o esquema de troca de entrada, descrito aqui, tem como base uma política de priorização aplicada automaticamente sempre que um novo aplicativo começa a capturar o áudio.

Com a finalidade de capturar o áudio, o Android diferencia dois tipos de aplicativos:

  • Aplicativos "comuns", instalados pelo usuário.
  • Aplicativos "privilegiados", pré-instalados no dispositivo. Esses últimos incluem o Google Assistente e todos os serviços de acessibilidade.

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

As regras de priorização para uso e compartilhamento de entrada de áudio são as seguintes:

  • Os aplicativos privilegiados têm prioridade mais alta do que os comuns.
  • Os aplicativos com IUs em primeiro plano visíveis têm prioridade mais alta do que aqueles em segundo plano.
  • Os aplicativos que capturam áudio de uma fonte sensível à privacidade têm prioridade mais alta do que aqueles que não fazem isso.
  • Não é possível a dois aplicativos comuns capturarem áudio ao mesmo tempo.
  • Em algumas situações, um aplicativo privilegiado pode compartilhar a entrada de áudio com outro aplicativo.
  • Se dois aplicativos em segundo plano da mesma prioridade estiverem capturando áudio, o último a ser iniciado terá prioridade mais alta.

Cenários de compartilhamento

Quando dois aplicativos tentam capturar o áudio, pode ser que ambos recebam o sinal de entrada ou um deles receba silêncio.

Estes são os quatro cenários principais:

  • Assistente + aplicativo comum
  • Serviço de acessibilidade + aplicativo comum
  • Dois aplicativos comuns
  • Chamada de voz + aplicativo comum

Assistente + aplicativo comum

O Assistente é um aplicativo privilegiado por ser pré-instalado e ter o papel RoleManager.ROLE_ASSISTANT. Qualquer outro aplicativo pré-instalado com esse papel é tratado de modo semelhante.

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

  • O Assistente (em primeiro ou segundo plano) pode receber áudio, a menos que outro aplicativo, usando uma fonte de áudio sensível à privacidade, já esteja fazendo a captura.

  • O aplicativo recebe o áudio, a não ser que o Assistente tenha um componente da IU visível na parte superior da tela.

Os dois aplicativos recebem o áudio somente quando o Assistente está em segundo plano e o outro aplicativo não está capturando de uma fonte de áudio sensível à privacidade.

Serviço de acessibilidade + aplicativo comum

Um AccessibilityService exige uma declaração rígida.

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

  • Se a IU do serviço estiver na parte superior, o serviço e o aplicativo receberão a entrada de áudio. Esse comportamento oferece funcionalidades como o controle de chamada de voz ou captura de vídeo por meio de comandos de voz.

  • Caso o serviço não esteja na parte superior, esse caso será tratado como quando há dois aplicativos comuns, conforme exibido abaixo.

Dois aplicativos comuns

Quando dois aplicativos estão capturando simultaneamente, somente um deles recebe áudio. O outro recebe silêncio.

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

  • Se nenhum aplicativo for sensível à privacidade, aquele que estiver com uma IU na parte superior receberá o áudio. Se nenhum aplicativo tiver IU, o último a iniciar a captura receberá o áudio.
  • Caso um dos aplicativos seja sensível à privacidade, ele receberá o áudio. O outro receberá silêncio, mesmo que tenha uma IU na parte superior ou que seja o último a iniciar a captura.
  • Se os dois aplicativos forem sensíveis à privacidade, o último a iniciar a captura receberá o áudio e o outro receberá silêncio.

Chamada de voz + aplicativo comum

Se o modo de áudio retornado por AudioManager.getMode() for MODE_IN_CALL ou MODE_IN_COMMUNICATION, uma chamada de voz está ativa.

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

Alterações de configuração

Quando vários aplicativos capturam áudio simultaneamente, somente um ou dois deles estão "ativos" (recebendo áudio), os outros estão silenciados (recebendo silêncio). Quando os aplicativos ativos mudam, a biblioteca de áudio pode reconfigurar os caminhos do áudio de acordo com estas regras:

  • O dispositivo de entrada de áudio para cada aplicativo ativo pode mudar (por exemplo, do microfone integrado para um fone de ouvido Bluetooth anexado).
  • O pré-processamento associado ao aplicativo ativo com a prioridade mais alta é habilitado. Todos os outros pré-processamentos são ignorados.

Como um aplicativo ativo pode ser silenciado quando um aplicativo de prioridade mais alta é ativado, você pode registrar um AudioManager.AudioRecordingCallback no objeto AudioRecord ou MediaRecorder para ser notificado quando houver mudança na configuração. Veja algumas possíveis alterações:

  • Captura silenciada ou com áudio ativado
  • Alteração no dispositivo
  • Alteração no pré-processamento
  • Alteração nas propriedades de stream (taxa de amostragem, máscara de canal, formato de exemplo)

Você precisa chamar AudioRecord.registerAudioRecordingCallback() antes do início da captura. O callback é executado somente quando o aplicativo está recebendo áudio e ocorre uma alteração.

O método onRecordingConfigChanged() retorna uma AudioRecordingConfiguration que contém o estado de captura do áudio atual. Para saber mais sobre a alteração, use os métodos a seguir:

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 aplicativo ativo com a prioridade mais alta.
getFormat()
Retorna as propriedades de stream. Os dados do áudio real recebidos pelo cliente sempre respeitam o formato obrigatório retornado por getClientFormat(). A biblioteca executa automaticamente a conversão necessária de formato, canal e reamostragem usados na interface de hardware para o formato especificado pelo cliente.
AudioRecord.getActiveRecordingConfiguration().
Retorna a configuração de gravação ativa.

Para ter uma visão geral de todas as gravações ativas no dispositivo, chame AudioManager.getActiveRecordingConfigurations().