Como compartilhar entradas de áudio

A entrada de áudio geralmente vem de um microfone integrado, 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 executando 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.

De qualquer forma, os aplicativos querem receber a entrada de áudio. Nesta página, usamos o termo "capturar" independentemente de o app estar gravando ou apenas ouvindo.

Se dois ou mais apps quiserem capturar áudio ao mesmo tempo, pode haver um problema ao enviar o sinal de áudio da mesma fonte para todos eles. Esta página descreve como o sistema Android compartilha entradas 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 de cada vez. Se algum app já estiver gravando ou ouvindo áudio, ele poderá criar um objeto AudioRecord, 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 aplicativo poderia começar a gravar. Quando isso acontecia, o app privilegiado era encerrado e o novo app capturava a entrada.

Mais uma mudança foi adicionada ao Android 9: somente apps executados em primeiro plano (ou um serviço em primeiro plano) poderiam capturar a entrada de áudio. Quando um app sem um serviço ou 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 a capturar áudio no momento.

Comportamento do Android 10

O comportamento antes do Android 10 era "por ordem de chegada". Depois que um app começa a capturar áudio, nenhum outro app pode acessar a entrada até que o que está capturando áudio seja interrompido.

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 de captura anterior continuará a ser executado, mas receberá silêncio. Em alguns casos, o sistema pode continuar a entregar á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 concorrentes pelo uso da saída de áudio. No entanto, a seleção de áudio é gerenciada por solicitações programáticas para ganhar e liberar foco, enquanto o esquema de alternância de entrada descrito aqui é baseado em uma política de priorização aplicada automaticamente sempre que um novo app começa a capturar áudio.

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

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

Além disso, um app é tratado de modo diferente se usa uma fonte de áudio que considera a 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 apps tentam capturar áudio, os dois podem receber o sinal de entrada ou um deles pode receber 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 app privilegiado porque está pré-instalado e tem 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 Google Assistente pode receber áudio, independente de estar em primeiro ou segundo plano, a menos que outro app que use uma fonte de áudio sensível à privacidade já esteja fazendo a captura.

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

Observe que os dois apps recebem áudio somente 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 + aplicativo comum

Um AccessibilityService requer uma declaração rigorosa.

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 o controle de uma ligação ou captura de vídeo com 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 app for sensível à privacidade, o app com uma interface na parte de cima vai receber o áudio. Se nenhum aplicativo tiver IU, o último a iniciar a captura receberá o áudio.
  • Se um dos apps for sensível à privacidade, ele vai receber áudio, e o outro app 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 que começou a capturar mais recentemente receberá o áudio e o outro receberá silêncio.

Chamada de voz + aplicativo comum

Uma ligação vai estar 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. Ela também oferece novos métodos em AudioRecord, MediaRecorder e AAudioStream que ativam e desativam a capacidade de capturar áudio simultaneamente, independente do caso de uso selecionado.

Os novos métodos são:

Quando setPrivacySensitive() for true, o caso de uso de captura será particular e nem mesmo um Google Assistente privilegiado poderá capturar 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 é.

Mudanças de configuração

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

  • O dispositivo de entrada de áudio para cada app ativo pode mudar, por exemplo, do microfone integrado para um fone de ouvido Bluetooth conectado.
  • O pré-processamento associado ao aplicativo ativo com a prioridade mais alta é habilitado. Todo o restante do pré-processamento é ignorado.

Como um app ativo pode ser silenciado quando outro de prioridade mais alta fica ativo, você pode registrar um AudioManager.AudioRecordingCallback no objeto AudioRecord ou MediaRecorder para receber uma notificação quando a configuração mudar. 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)

É necessário 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 contendo o estado atual de captura de áudio. Use os seguintes métodos para saber mais sobre a mudança:

isClientSilenced()
Retorna "true" 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 fluxo. Os dados de áudio reais recebidos pelo cliente sempre respeitam o formato exigido retornado por getClientFormat(). O framework realiza automaticamente a conversão necessária de reamostragem, canal e formato do formato usado 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().